Added shaders and doomscript from the build.

This commit is contained in:
Justin Marshall
2026-08-09 04:23:10 -07:00
parent 82cfb1972d
commit 1d0c9d6657
734 changed files with 19587 additions and 0 deletions
@@ -0,0 +1,20 @@
// this is normalized window space, not strict openGL window space that uses integer viewport values.
float4 window;
window.xy = screenPosToTexcoord( fragment.position.xy, $renderPositionToViewTexture );
window.z = tex2Ddepth( $viewDepthMap, window.xy );
window.w = 1.0;
float4 texcoord;
texcoord.x = dot4( window, $windowPosToProjectedTexS );
texcoord.y = dot4( window, $windowPosToProjectedTexT );
texcoord.z = dot4( window, $windowPosToProjectedTexR );
texcoord.w = dot4( window, $windowPosToProjectedTexQ );
texcoord.xyz /= texcoord.w;
half4 lpm = h4tex2D( $lightProjectMap, texcoord.xy );
half4 lfm = h4tex2D( $lightFalloffMap, float2( texcoord.z, 0.5 ) );
half4 color = lpm * lfm * $lightColor;
color.xyz *= $lightFade.x;
@@ -0,0 +1,105 @@
// Use the screen pos and the depth buffer value at this location to compute the local
// position within the decal box
float3 window;
window.xy = screenPosToTexcoord( fragment.position.xy, $renderPositionToViewTexture );
// fetch the window space depth value
//#ifndef PS3
window.z = tex2Ddepth( $viewDepthMap, window.xy );
//#else
// // This depth reconstruct fixes the decal artifacts on the ps3
//
// half4 dt = h4tex2D( $viewDepthMap, window.xy );
// float4 d4;
// d4.w = floor( dt.w * half( 255.0 + 1.0 / 256.0 ) + 0.1 ) / 256;
// d4.x = floor( dt.x * half( 255.0 + 1.0 / 256.0 ) + 0.1 ) / 256 / 256;
// d4.y = floor( dt.y * half( 255.0 + 1.0 / 256.0 ) + 0.1 ) / 256 / 256 / 256;
// const float depth = ( d4.w + d4.x + d4.y );
// window.z = depth;
//#endif
float4 wclip = float4( window.xyz, 1.0 );
// transform to global space
float4 worldPos;
worldPos.x = dot( wclip, $decalPosToLocalBoxSpaceX );
worldPos.y = dot( wclip, $decalPosToLocalBoxSpaceY );
worldPos.z = dot( wclip, $decalPosToLocalBoxSpaceZ );
worldPos.w = dot( wclip, $decalPosToLocalBoxSpaceW );
worldPos /= worldPos.w;
// transform to local space of box
float3 center = fragment.texcoord4.xyz;
// translate to origin of box
worldPos.xyz -= center;
// rotate
float3 tangent = normalize( fragment.texcoord1.xyz );
float3 bitangent = normalize( fragment.texcoord2.xyz );
float3 normal = normalize( fragment.texcoord3.xyz );
float3 localPos = worldPos.xyz;
localPos.x = dot3( worldPos, tangent );
localPos.y = dot3( worldPos, bitangent );
localPos.z = dot3( worldPos, normal );
// scale back down to [-1,1]
float3 sizes = fragment.color.xyz;
localPos.xyz *= sizes;
// Use the local space pos to construct the texture coordinates for lookup into the decal texture
float3 tc = saturate( ( localPos * 0.5 ) + 0.5 );
tc.x = 1.0 - tc.x;
// To prevent edge filtering bleed-through, apply an 8-texel inset to the texcoords (for 3 mip levels)
float4 inset;
inset.xy = 8.0 / float2( fragment.texcoord0.y * $transSortAtlasDim.x, fragment.texcoord0.w * $transSortAtlasDim.y );
inset.zw = _float2( 0.0 );
clip( min( tc.xyzx - inset, _float4( 1.0 ) - ( tc.xyzx + inset ) ) );
// GK: Test performing the divide by w after clip
//clip( min( extrudePos.w + extrudePos.xyzx, extrudePos.w - extrudePos.xyzx ) );
float edgefade = 1.0;
#if 1 //ndef PC
// spherical edge fade test
float dist = dot( localPos, localPos );
dist = pow( dist, 4.0 );
edgefade = 1.0 - dist;
// result.color = edgefade;
// result.color.w = 1;
// return;
#else
// TODO: Test on consoles
// Fade out decals so they don't draw on perpendicular surfaces
float3 surfNormal = normal;
float3 texelNormal = normalize( cross( ddx( worldPos.xyz ), ddy( worldPos.xyz ) ) );
float angleDot = dot3( surfNormal, texelNormal );
clip( angleDot - 0.7 );
#endif
//#if 1
// texcoord0 has the scale/bias into the image atlas
float2 texcoord;
texcoord.x = tc.x * fragment.texcoord0.y + fragment.texcoord0.x;
texcoord.y = tc.y * fragment.texcoord0.w + fragment.texcoord0.z;
//half fog = saturate( exp2( fragment.texcoord4.w ) );
half fog = fragment.texcoord4.w;
// Just want the texcoords, the rest of the shader will determin what to do with them
// half4 final = tex2D( $transMap, texcoord );
// final.w *= fragment.color.w; // fade based on time
// final.w *= edgefade; // apply edge fade
//#else
// half4 final;
// final.xy = tc.xy;
// final.z = 0.0;
// final.w = 1.0;
//#endif
@@ -0,0 +1,18 @@
float2 tc = fragment.texcoord1.xy;
// To prevent edge filtering bleed-through, apply an 8-texel inset to the texcoords (for 3 mip levels)
float2 inset;
inset.xy = 8.0 / float2( fragment.texcoord0.y * $transSortAtlasDim.x, fragment.texcoord0.w * $transSortAtlasDim.y );
clip( min( tc - inset, _float2( 1.0 ) - ( tc + inset ) ) );
// texcoord0 has the scale/bias into the image atlas
float2 texcoord;
texcoord.x = tc.x * fragment.texcoord0.y + fragment.texcoord0.x;
texcoord.y = tc.y * fragment.texcoord0.w + fragment.texcoord0.z;
half fog = saturate( exp2( fragment.texcoord1.w ) );
half4 final = tex2D( $transMap, texcoord );
final.w *= fragment.color.w;
+571
View File
@@ -0,0 +1,571 @@
/*
Do not use render parms in this file directly or they will be included in every single
vertex and fragment program which may come at a significant performance penalty.
For convenience render parms may be used in a #define declared in this file and such
a define may then be used in the actual vertex or fragment program that needs it.
*/
#if defined( XBOX )
#define BRANCH [branch]
#define IFANY [ifAny]
#elif defined( PS3 )
#define BRANCH [branch]
#define IFANY
#else
#define BRANCH
#define IFANY
#endif
static float dot2( float2 a, float2 b ) { return dot( a, b ); }
static float dot3( float3 a, float3 b ) { return dot( a, b ); }
static float dot3( float3 a, float4 b ) { return dot( a, b.xyz ); }
static float dot3( float4 a, float3 b ) { return dot( a.xyz, b ); }
static float dot3( float4 a, float4 b ) { return dot( a.xyz, b.xyz ); }
static float dot4( float4 a, float4 b ) { return dot( a, b ); }
static float dot4( float2 a, float4 b ) { return dot( float4( a, 0, 1 ), b ); }
#ifdef PC_D3D
#define sampler2D Texture2D
#define samplerCUBE TextureCube
#define samplerRECT Texture2D // FIXME: Rect support
#endif
#ifdef GLSL
#define anyEqual( x, y ) any( equal( x, y ) )
#define anyNotEqual( x, y ) any( notEqual( x, y ) )
#define anyNotEqualZero( x ) max( sign( x ), 0.0 )
#define fmod( x, y ) mod( x, y )
#define SineCosine( x, s, c ) s = sin( x ); c = cos( x );
#else
#define anyEqual( x, y ) any( (x) == (y) )
#define anyNotEqual( x, y ) any( (x) != (y) )
#define anyNotEqualZero( x ) any( (x) )
#define greaterThanEqual( x, y ) ( (x) >= (y) )
#define SineCosine( x, s, c ) sincos( x, s, c );
static half dot2( half2 a, half2 b ) { return dot( a, b ); }
static half dot3( half3 a, half3 b ) { return dot( a, b ); }
static half dot3( half3 a, half4 b ) { return dot( a, b.xyz ); }
static half dot3( half4 a, half3 b ) { return dot( a.xyz, b ); }
static half dot3( half4 a, half4 b ) { return dot( a.xyz, b.xyz ); }
static half dot4( half4 a, half4 b ) { return dot( a, b ); }
static half dot4( half2 a, half4 b ) { return dot( half4( a, 0, 1 ), b ); }
#define sampler2DShadow sampler2D
#define samplerCUBEShadow samplerCUBE
#define samplerRECTShadow samplerRECT
#endif
static half PAGE_SIZE = 128;
static half PAGE_BORDER = 4;
static half PAGE_SIZE_LOG2 = 7;
static half PAYLOAD_SIZE = PAGE_SIZE - 2 * PAGE_BORDER;
static half PAYLOAD_SIZE_LOG2 = 6.907;
#ifdef XBOX
// these are here because HLSL does not implement vector constructors with a single scalar parameter
half2 _half2( float x ) { return half2( x, x ); }
half3 _half3( float x ) { return half3( x, x, x ); }
half4 _half4( float x ) { return half4( x, x, x, x ); }
float2 _float2( float x ) { return float2( x, x ); }
float3 _float3( float x ) { return float3( x, x, x ); }
float4 _float4( float x ) { return float4( x, x, x, x ); }
static float4 h4tex2D( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 h4tex2Dproj( sampler2D image, float3 texcoord ) { return tex2Dproj( image, float4( texcoord.xy, 0, texcoord.z ) ); }
static float4 texPhys( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 texPhys( sampler2D image, float2 texcoord, float2 dx, float2 dy ) { return tex2D( image, texcoord, dx, dy ); }
static float4 h4texPhys( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 h4texPhys( sampler2D image, float2 texcoord, float2 dx, float2 dy ) { return tex2D( image, texcoord, dx, dy ); }
// return the depth value at texcoord.xy
static float tex2Ddepth( sampler2D image, float2 texcoord ) { return 1.0 - tex2D( image, texcoord ).x; }
static float tex2Ddepth_fast( sampler2D image, float2 texcoord ) { return 1.0 - tex2D( image, texcoord ).x; }
// compare texcoord.z with the depth value at texcoord.xy and return 1 if less and 0 if larger equal
static float shadow2Ddepth( sampler2DShadow image, float3 texcoord ) { return float( ( 1.0 - tex2D( image, texcoord.xy ).x ) >= texcoord.z ); }
static float4 swizzleColor( float4 color ) { return color.abgr; }
static float2 screenPosToTexcoord( float2 pos, float4 bias_scale ) { return ( pos * bias_scale.zw + bias_scale.xy ); }
bool bHardwareSkinning : register(b1);
bool bHardwareMorphing : register(b2);
#endif
#ifdef PS3
#define _half2( x ) half2( x )
#define _half3( x ) half3( x )
#define _half4( x ) half4( x )
#define _float2( x ) float2( x )
#define _float3( x ) float3( x )
#define _float4( x ) float4( x )
static float4 texPhys( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 texPhys( sampler2D image, float2 texcoord, float2 dx, float2 dy ) { return tex2D( image, texcoord, dx, dy ); }
static half4 h4texPhys( sampler2D image, float2 texcoord ) { return h4tex2D( image, texcoord ); }
static half4 h4texPhys( sampler2D image, float2 texcoord, float2 dx, float2 dy ) { return h4tex2D( image, texcoord, dx, dy ); }
// return the depth value at texcoord.xy
static float tex2Ddepth( sampler2D image, float2 texcoord ) { return texDepth2D_precise( image, texcoord ); }
static float tex2Ddepth_fast( sampler2D image, float2 texcoord ) {
// Perform most accurate integer reconstruction using a half precision multiply.
// Make sure the assember code looks like this:
//
// TEXR H0, R1, TEX0;
// MULH H0, H0, {0x437f0000(255), 0x00000000(0), 0x00000000(0), 0x00000000(0)}.x;
// DP3R R1.z, H0, {0x3b800000(0.00390625), 0x37800000(1.52588e-005), 0x33800000(5.96046e-008), 0x00000000(0)};
//
half4 dt = h4tex2D( image, texcoord ) * half( 255.0 );
return dot( dt, float4( 1.0 / 256, 1.0 / 256 / 256, 1.0 / 256 / 256 / 256, 0.0 ) );
}
// compare the depth value at texcoord.xy with texcoord.z and return 0 if less and 1 if larger equal
static float shadow2Ddepth( sampler2DShadow image, float3 texcoord ) { return tex2D( image, texcoord ).x; }
static float4 swizzleColor( float4 color ) { return color; }
static float2 screenPosToTexcoord( float2 pos, float4 bias_scale ) { return ( pos * bias_scale.zw + bias_scale.xy ); }
bool hardwareSkinning : b1;
bool hardwareMorphing : b2;
#endif
#if defined( PC_D3D )
// these are here because HLSL does not implement vector constructors with a single scalar parameter
half2 _half2( float x ) { return half2( x, x ); }
half3 _half3( float x ) { return half3( x, x, x ); }
half4 _half4( float x ) { return half4( x, x, x, x ); }
float2 _float2( float x ) { return float2( x, x ); }
float3 _float3( float x ) { return float3( x, x, x ); }
float4 _float4( float x ) { return float4( x, x, x, x ); }
SamplerState samplerGeneric : register( s0 ); // FIXME
static float4 tex2D( sampler2D image, float2 texcoord ) { return image.Sample( samplerGeneric, texcoord ); }
static float4 tex2Dproj( sampler2D image, float3 texcoord ) { return image.Sample( samplerGeneric, texcoord ); }
static float4 tex2DGrad( sampler2D image, float2 texcoord, float2 dx, float2 dy ) { return image.SampleGrad( samplerGeneric, texcoord, dx, dy ); }
static float4 tex2Dlod( sampler2D image, float4 texcoord ) { return image.SampleLevel( samplerGeneric, texcoord.xy, texcoord.w, 0 ); }
static float4 tex2Dbias( sampler2D image, float4 texcoord ) { return image.SampleBias( samplerGeneric, texcoord.xy, texcoord.w ); }
static float4 texCUBE( samplerCUBE image, float3 texcoord ) { return image.Sample( samplerGeneric, texcoord ); }
static float4 texCUBElod( samplerCUBE image, float4 texcoord ) { return image.SampleLevel( samplerGeneric, texcoord.xyz, texcoord.w ); }
static float4 h4tex2D( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 h4tex2Dproj( sampler2D image, float3 texcoord ) { return tex2Dproj( image, float4( texcoord.xy, 0, texcoord.z ) ); }
static float4 texPhys( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 texPhys( sampler2D image, float2 texcoord, float2 dx, float2 dy ) { return tex2DGrad( image, texcoord, dx, dy ); }
static float4 h4texPhys( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 h4texPhys( sampler2D image, float2 texcoord, float2 dx, float2 dy ) { return tex2DGrad( image, texcoord, dx, dy ); }
// return the depth value at texcoord.xy
static float tex2Ddepth( sampler2D image, float2 texcoord ) { return 1.0 - tex2D( image, texcoord ).x; }
static float tex2Ddepth_fast( sampler2D image, float2 texcoord ) { return 1.0 - tex2D( image, texcoord ).x; }
// compare texcoord.z with the depth value at texcoord.xy and return 1 if less and 0 if larger equal
static float shadow2Ddepth( sampler2DShadow image, float3 texcoord ) { return float( ( 1.0 - tex2D( image, texcoord.xy ).x ) >= texcoord.z ); }
static float4 swizzleColor( float4 color ) { return color.rgba; }
static float2 screenPosToTexcoord( float2 pos, float4 bias_scale ) { return ( pos * bias_scale.zw + bias_scale.xy ); }
bool bHardwareSkinning : register(b1);
bool bHardwareMorphing : register(b2);
#elif defined( PC )
#define _half2( x ) half2( x )
#define _half3( x ) half3( x )
#define _half4( x ) half4( x )
#define _float2( x ) float2( x )
#define _float3( x ) float3( x )
#define _float4( x ) float4( x )
static float4 h4tex2D( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 h4tex2Dproj( sampler2D image, float3 texcoord ) { return tex2Dproj( image, texcoord ); }
static float4 texPhys( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 texPhys( sampler2D image, float2 texcoord, float2 dx, float2 dy ) { return tex2D( image, texcoord, dx, dy ); }
static float4 h4texPhys( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ); }
static float4 h4texPhys( sampler2D image, float2 texcoord, float2 dx, float2 dy ) { return tex2D( image, texcoord, dx, dy ); }
// return the depth value at texcoord.xy
static float tex2Ddepth( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ).x; }
static float tex2Ddepth_fast( sampler2D image, float2 texcoord ) { return tex2D( image, texcoord ).x; }
// compare the depth value at texcoord.xy with texcoord.z and return 0 if less and 1 if larger equal
static float shadow2Ddepth( sampler2DShadow image, float3 texcoord ) { return tex2D( image, texcoord ).x; }
static float4 swizzleColor( float4 color ) { return color; }
static float2 screenPosToTexcoord( float2 pos, float4 bias_scale ) { return ( pos * bias_scale.zw + bias_scale.xy ); }
#endif
static const half4 matrixRGB1toCoCg1YX = half4( 0.50, 0.0, -0.50, 0.50196078 ); // Co
static const half4 matrixRGB1toCoCg1YY = half4( -0.25, 0.5, -0.25, 0.50196078 ); // Cg
static const half4 matrixRGB1toCoCg1YZ = half4( 0.0, 0.0, 0.0, 1.0 ); // 1.0
static const half4 matrixRGB1toCoCg1YW = half4( 0.25, 0.5, 0.25, 0.0 ); // Y
static const half4 matrixCoCg1YtoRGB1X = half4( 1.0, -1.0, 0.0, 1.0 );
static const half4 matrixCoCg1YtoRGB1Y = half4( 0.0, 1.0, -0.50196078, 1.0 ); // -0.5 * 256.0 / 255.0
static const half4 matrixCoCg1YtoRGB1Z = half4( -1.0, -1.0, 1.00392156, 1.0 ); // +1.0 * 256.0 / 255.0
// uses texel space coordinates, not normalized coordinates
static float ComputeLOD( float2 virtCoords ) {
float2 dx = ddx( virtCoords.xy );
float2 dy = ddy( virtCoords.xy );
float px = dot2( dx, dx );
float py = dot2( dy, dy );
float maxLod = 0.5 * log2( max( px, py ) ); // log2(sqrt()) = 0.5*log2()
return maxLod;
}
// uses texel space coordinates, not normalized coordinates
static float ComputeAnisoLOD( float2 virtCoords, float maxAnisoLog2 ) {
float2 dx = ddx( virtCoords.xy );
float2 dy = ddy( virtCoords.xy );
float px = dot2( dx, dx );
float py = dot2( dy, dy );
float maxLod = 0.5 * log2( max( px, py ) ); // log2(sqrt()) = 0.5*log2()
float minLod = 0.5 * log2( min( px, py ) );
return maxLod - min( maxAnisoLog2, maxLod - minLod );
}
static float4 ComputeVirtualLOD( float4 filterParms, float4 feedbackFloat, float4 virtMapping, float2 virtCoords ) {
// Used for the land generation tool path.
float drawBias = filterParms.x;
float maxAnisoLog2 = filterParms.z;
float widthInPages = feedbackFloat.y;
// take just the fractional part of the original texture coordinate to give texture wrapping
// scale and bias it by the source to virtual texture mapping
float4 virtualTexCoord;
virtualTexCoord.zw = _float2( 0.0 );
virtualTexCoord.xy = frac( virtCoords );
virtualTexCoord.xy = virtualTexCoord.xy * virtMapping.xy + virtMapping.zw;
// look up the proper LOD in the dedicated LOD texture, based on the original, non-wrapped,
// non-paged texture coordinates to avoid discontinuities. Still need to multiply by virtualMapping.xy
// to account for the dimensions of the original texture.
virtualTexCoord.w = ComputeAnisoLOD( virtCoords * virtMapping.xy * widthInPages * PAYLOAD_SIZE, maxAnisoLog2 );
// adjust for the LOD bias already applied in the virtToPhysPage sampler (log2TexelSizeRatio)
virtualTexCoord.w -= PAYLOAD_SIZE_LOG2 + drawBias;
return virtualTexCoord;
}
#if defined( XBOX ) || ( defined( ATI ) && !defined( ATI_CLAMPED_ANISO ) )
// use the virtual texture coordinate instead of the physical texture coordinate for the anisotropic texture lookup
#define USE_VIRTUAL_ANISO_FOOTPRINT
#endif
// bias the page table lookup anticipating an anisotropic texture lookup
// this is expensive but may be a nice quality improvement for high end PCs
//#define USE_ANISO_PAGE_TABLE_LOOKUP
static float4 PageTableBiasForAniso( float2 virtCoords ) {
const float minAnisoBias = -2; // -log2( maxAniso )
// calculate a bias for the page table lookup based on the size of the anisotropic footprint
float2 dx = ddx( virtCoords.xy );
float2 dy = ddy( virtCoords.xy );
float px = dot2( dx, dx );
float py = dot2( dy, dy );
float maxLod = 0.5 * log2( max( px, py ) ); // log2(sqrt()) = 0.5*log2()
float minLod = 0.5 * log2( min( px, py ) );
float anisoBias = max( minLod - maxLod, minAnisoBias );
return float4( virtCoords.x, virtCoords.y, 0, anisoBias );
}
#ifdef USE_ANISO_PAGE_TABLE_LOOKUP
#define tex2DPageTable( sampler, coords ) tex2Dbias( sampler, PageTableBiasForAniso( coords ) )
#else
#define tex2DPageTable( sampler, coords ) tex2D( sampler, coords )
#endif
//#define PAGE_TABLE_ONLY_8888
#if defined( PS3 ) || defined( XBOX )
#define PAGE_TABLE_ONLY_565
#endif
//#define MAPPING_IMAGE_3X_FLOAT32
//#define MAPPING_IMAGE_2X_FIXED16
#if defined( PAGE_TABLE_ONLY_8888 )
// using only the page table in 8-bit per component RGBA format
#define UniqueVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, coords, 32 )
#define UniqueDiffuseOnlyVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, coords, 32 )
#define UniqueDiffuseOnly2VirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, coords, 32 )
#define VmtrVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, coords, 16 )
#define VmtrVirtualLODToPhysical( virtMapping, coords ) VirtualToPhysical2( $vmtrPageTableMap, coords, 16 ).xy
static float3 VirtualToPhysical2( sampler2D virtToPhysPage, float2 virtCoords, float physPagesWide ) {
// constants
const float pageWidth = 128;
const float pageBorder = 4;
//const float physPagesWide = 32;
#if defined( PS3 ) || defined( XBOX )
const float floatToByte = 255.0 + 1.0 / 256;
#else
const float floatToByte = 255.0;
#endif
// derived constants
const float pageFracScale = ( pageWidth - 2 * pageBorder ) / pageWidth / physPagesWide;
const float borderOffset = pageBorder / pageWidth / physPagesWide;
const float4 texScale = {
floatToByte / physPagesWide,
floatToByte / physPagesWide,
floatToByte * 1.0 / 16.0,
floatToByte * 256.0 / 16.0
};
const float4 texBias = { borderOffset, borderOffset, 0, 0 };
// translation
float4 physPage = tex2DPageTable( virtToPhysPage, virtCoords ) * texScale + texBias;
float2 pageFrac = frac( virtCoords * ( physPage.z + physPage.w ) );
float3 physCoord;
physCoord.xy = pageFrac * pageFracScale + physPage.xy;
physCoord.z = ( physPage.z + physPage.w ) * pageFracScale;
return physCoord;
}
#elif defined( PAGE_TABLE_ONLY_565 )
// using only the page table in 565 RGB format
#define UniqueVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, coords, 32 )
#define UniqueDiffuseOnlyVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, coords, 32 )
#define UniqueDiffuseOnly2VirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, coords, 32 )
#define VmtrVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, coords, 16 )
#define VmtrVirtualLODToPhysical( virtMapping, coords ) VirtualToPhysical2( $vmtrPageTableMap, coords, 16 ).xy
static float3 VirtualToPhysical2( sampler2D virtToPhysPage, float2 virtCoords, float physPagesWide ) {
// constants
const float pageWidth = 128;
const float pageBorder = 4;
//const float physPagesWide = 32;
#if defined( PS3 )
const float floatToPagesWide = ( 255.0 + 1.0 / 256 ) / 256.0 * physPagesWide;
const float floatToMip = ( 255.0 + 1.0 / 256 ) / 256.0 * 64.0;
#elif defined( XBOX )
const float floatToPagesWide = ( 31.0 + 1.0 / 33.0 ) / 32.0 * physPagesWide;
const float floatToMip = ( 63.0 + 1.0 / 65.0 );
#else
const float floatToPagesWide = 255.0 / 256.0 * physPagesWide;
const float floatToMip = 255.0 / 256.0 * 64.0;
#endif
// derived constants
const float pageFracScale = ( pageWidth - 2 * pageBorder ) / pageWidth / physPagesWide;
const float borderOffset = pageBorder / pageWidth / physPagesWide;
const float4 texScale = {
floatToPagesWide,
floatToMip,
floatToPagesWide,
0
};
float4 texBias = { 0, 1.0 / 4096.0, 0, 0 };
// translation
half4 physPage = tex2DPageTable( virtToPhysPage, virtCoords ) * texScale + texBias; // NOTE: must be half4 for PS3 ?
physPage.y = exp2( physPage.y );
physPage = floor( physPage );
float2 pageFrac = frac( virtCoords * physPage.y );
float3 physCoord;
physCoord.xy = pageFrac * pageFracScale + physPage.xz / physPagesWide + borderOffset;
physCoord.z = physPage.y * pageFracScale;
return physCoord;
}
#elif defined( MAPPING_IMAGE_2X_FIXED16 )
// using two unsigned fixed point 16-bit mapping textures, one with a single channel and one with two channels
#define UniqueVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalUniqueMappingsMap0, $physicalUniqueMappingsMap1, coords )
#define UniqueDiffuseOnlyVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalUniqueDiffuseOnlyMappingsMap0, $physicalUniqueDiffuseOnlyMappingsMap1, coords )
#define UniqueDiffuseOnly2VirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalUniqueDiffuseOnly2MappingsMap0, $physicalUniqueDiffuseOnly2MappingsMap1, coords )
#define VmtrVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalVmtrMappingsMap0, $physicalVmtrMappingsMap1, coords )
#define VmtrVirtualLODToPhysical( virtMapping, coords ) VirtualToPhysical2( $vmtrPageTableMap, $physicalVmtrMappingsMap0, $physicalVmtrMappingsMap1, coords ).xy
static float3 VirtualToPhysical2( sampler2D virtToPhysPage, sampler2D physPageToXform0, sampler2D physPageToXform1, float2 virtCoords ) {
half2 physPage = tex2DPageTable( virtToPhysPage, virtCoords ).xy;
float4 xform0 = tex2D( physPageToXform0, physPage ) * 32.0;
float4 xform1 = tex2D( physPageToXform1, physPage ) * 32.0;
float3 physCoord;
physCoord.xy = virtCoords * xform0.y + xform1.xw - 30.0;
physCoord.z = 0.0f;
return physCoord;
}
#elif defined( MAPPING_IMAGE_3X_FLOAT32 )
// using three single channel float 32 mapping textures, one for each component
#define UniqueVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalUniqueMappingsMap0, $physicalUniqueMappingsMap1, $physicalUniqueMappingsMap2, coords )
#define UniqueDiffuseOnlyVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalUniqueDiffuseOnlyMappingsMap0, $physicalUniqueDiffuseOnlyMappingsMap1, $physicalUniqueDiffuseOnlyMappingsMap2, coords )
#define UniqueDiffuseOnly2VirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalUniqueDiffuseOnly2MappingsMap0, $physicalUniqueDiffuseOnly2MappingsMap1, $physicalUniqueDiffuseOnly2MappingsMap2, coords )
#define VmtrVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalVmtrMappingsMap0, $physicalVmtrMappingsMap1, $physicalVmtrMappingsMap2, coords )
#define VmtrVirtualLODToPhysical( virtMapping, coords ) VirtualToPhysical2( $vmtrPageTableMap, $physicalVmtrMappingsMap0, $physicalVmtrMappingsMap1, $physicalVmtrMappingsMap2, coords ).xy
static float3 VirtualToPhysical2( sampler2D virtToPhysPage, sampler2D physPageToXform0, sampler2D physPageToXform1, sampler2D physPageToXform2, float2 virtCoords ) {
half2 physPage = tex2DPageTable( virtToPhysPage, virtCoords ).xy;
float xform0 = tex2D( physPageToXform0, physPage ).x;
float xform1 = tex2D( physPageToXform1, physPage ).x;
float xform2 = tex2D( physPageToXform2, physPage ).x;
float3 physCoord;
physCoord.xy = virtCoords * xform0 + float2( xform1, xform2 );
physCoord.z = 0.0f;
return physCoord;
}
#else
// using a single 4 channel float 32 mapping texture
#define UniqueVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalUniqueMappingsMap0, coords )
#define UniqueDiffuseOnlyVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalUniqueDiffuseOnlyMappingsMap0, coords )
#define UniqueDiffuseOnly2VirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalUniqueDiffuseOnly2MappingsMap0, coords )
#define VmtrVirtualToPhysical( coords ) VirtualToPhysical2( $pageTableMap, $physicalVmtrMappingsMap0, coords )
#define VmtrVirtualLODToPhysical( virtMapping, coords ) VirtualLODToPhysical2( $vmtrPageTableMap, $physicalVmtrMappingsMap0, ComputeVirtualLOD( $physicalVmtrFilterParms, $virtualTextureFeedbackFloat, virtMapping, coords ) )
static float3 VirtualToPhysical2( sampler2D virtToPhysPage, sampler2D physPageToXform0, float2 virtCoords ) {
half2 physPage = tex2DPageTable( virtToPhysPage, virtCoords ).xy;
float4 xform = tex2D( physPageToXform0, physPage );
float3 physCoord;
physCoord.xy = virtCoords * xform.x + xform.zw;
physCoord.z = xform.y;
return physCoord;
}
static float2 VirtualLODToPhysical2( sampler2D virtToPhysPage, sampler2D physPageToXform0, float4 virtCoords ) {
half2 physPage = tex2Dlod( virtToPhysPage, virtCoords ).xy;
float4 xform = tex2D( physPageToXform0, physPage );
return virtCoords.xy * xform.x + xform.zw;
}
#endif
static float ComputeSoftParticleScale( sampler2D image, float2 tc, float interpolatedZOverW, float softness ) {
// This instruction handles the 1.0 - depth calc automatically when using an inverted depth buffer
float depth = tex2Ddepth( image, tc );
// Approximate a linear depth difference
float r1 = 1.0 / ( 1.0 - depth );
float r2 = 1.0 / ( 1.0 - interpolatedZOverW );
return saturate( ( r1 - r2 ) * softness );
}
static half4 ComputeAnimCrossFadeColor( sampler2D image, float2 tc0, float2 tc1, float frameFrac ) {
// For strip animations, we need to cross-fade
half4 result0 = tex2D( image, tc0 ) * ( 1.0 - frameFrac );
half4 result1 = tex2D( image, tc1 ) * ( frameFrac ); // when frameFrac is 0, no contribution
return ( result0 + result1 );
}
// the 'distortVec' is in the range [-1.0, 1.0] for each component where 1.0 is the
// full screen width or height respectively
// the 'blur' value is in the range [0.0, 1.0] where 1.0 offsets the mip level by 8
static float4 ComputeDistortion( float2 distortVec, float blur ) {
// The distortion vector is usually very small so store a close to normalized vector
// in 'xy' and store a scale value in 'z'.
// The blur value is moved in the range [0.5, 1.0] which allows multiple distortions
// to be blended with GL_ONE_MINUS_DST_ALPHA GL_DST_ALPHA. The 'blur' (alpha channel) in
// the distortion map is initialized to zero such that the first distortion fully contributes
// and then consecutive distortions will blend in with a value in the range [0.0, 0.5].
// Blending based on the blur value is of course wrong but it works if no blurring is applied.
// Also, as the blur value goes up, additional distortions contribute less which is
// fine because the distortions won't be noticeable when there is a lot of blurring.
// A linear blend of the two vectors with separate scale values does not result in the
// same vector as a linear blend of the original vectors. However, the resulting vector
// is still nicely bounded between the original vectors and representative of accumulated
// distortions.
// To decode the distortion vector and blur value in the post process we use:
// half4 distortion = h4tex2D( $postDistortionMap, texcoord.xy ) - ( 127.0 / 255.0 );
// perturb += distortion.xy * distortion.z;
// blur += saturate( distortion.w ) * 16;
float4 final;
final.z = 0.125 + sqrt( dot( distortVec, distortVec ) );
final.xy = distortVec / final.z;
final.w = blur * 0.5;
return final + ( 127.0 / 255.0 );
}
static half2 ComputeTransAtlasCoord( half2 tc, half4 scaleBias ) {
// Figure out half texel, pick fraction from texture coordinates and clamp it inside [ 0+halfTexel, 1-halfTexel ]
half2 halfScale = scaleBias.xy * _half2( 0.5 );
half2 result = max( min( frac( tc ), _half2( 1.0 ) - halfScale ), halfScale );
// Scale and bias clamped texture coordinates
return result * scaleBias.xy + scaleBias.zw;
}
static float4 ComputeDistortionMV( float2 distortVec, float blur ) {
float4 final;
final.xy = saturate( distortVec * 0.5 + 0.5 );
final.z = blur * 0.5 + 0.5;
final.w = 1.0;
return final;
}
static float3 CoCgScYToRGB( float4 CoCgScY ) {
float3 rgb;
CoCgScY.z = ( CoCgScY.z * 31.875 ) + 1.0; //z = z * 255.0/8.0 + 1.0
CoCgScY.z = 1.0 / CoCgScY.z;
CoCgScY.xy *= CoCgScY.z;
rgb.x = dot4( CoCgScY, matrixCoCg1YtoRGB1X );
rgb.y = dot4( CoCgScY, matrixCoCg1YtoRGB1Y );
rgb.z = dot4( CoCgScY, matrixCoCg1YtoRGB1Z );
return rgb;
}
static float4 CoCgScYToRGB1( float4 CoCgScY ) {
float4 rgba;
rgba.xyz = CoCgScYToRGB( CoCgScY );
rgba.w = 1;
return rgba;
}
static float3 ScaleSpecular( float3 unscaled, float factor ) {
return ( unscaled * 8.0 ) / ( factor * 255.0 + 8.0 );
}
//#define FEEDBACK_FORMAT_FLOAT32
static float4 CalculateFeedback( float2 texCoords, float4 feedbackParms, float4 filterParms ) {
float4 feedback;
float bias = filterParms.y;
float maxAnisoLog2 = filterParms.z;
float widthInPages = feedbackParms.y;
// xy is the integral page coordinates
feedback.xy = texCoords * widthInPages;
// compute the desired LOD for anisotropic filtering
float desiredLod = ComputeAnisoLOD( feedback.xy * PAYLOAD_SIZE, maxAnisoLog2 ) + bias;
// z is the lod level, never adjust below 0
feedback.z = max( 0.0, desiredLod );
// w holds the virtual texture index
feedback.w = feedbackParms.x;
return feedback;
}
/*
pageX = ( data[0] & 0xFF ) + ( data[2] & 0x0F ) << 8 );
pageY = ( data[1] & 0xFF ) + ( data[2] & 0xF0 ) << 4 );
pageLOD = ( data[3] & 0x0F );
pageSource = ( data[3] & 0xF0 ) >> 4;
*/
static float4 PackFeedback( float4 feedback ) {
#ifdef FEEDBACK_FORMAT_FLOAT32
return feedback;
#else
feedback = floor( feedback ) / 256.0;
float2 xy_low = frac( feedback.xy + 0.5 / 256.0 );
float2 xy_high = floor( feedback.xy ) / 256.0;
float4 color;
color.xy = xy_low;
color.z = xy_high.y * 16.0 + xy_high.x;
color.w = feedback.w * 16.0 + feedback.z;
#if defined( XBOX )
return color.zyxw; // stored as B-G-R-A
#elif defined( PS3 )
return color.yzwx; // stored as A-R-G-B
#else
return color;
#endif
#endif
}
@@ -0,0 +1,39 @@
/*
==================================================================================
CALC_POSITION_AUTOSPRITE1
==================================================================================
*/
#template CALC_POSITION_AUTOSPRITE1( resultPosition, midpoint, viewLeft, viewUp, tangent )
{
// Normals and tangents are stored as unsigned bytes - need to expand back to [-1,1] range
float3 parms = tangent;
parms.yz = parms.yz * 2.0 - 1.0;
float radius = parms.x * 255.0;
float signLeft = parms.y;
float signUp = parms.z;
float3 scaledLeft = normalize( viewLeft ) * radius;
float3 scaledUp = normalize( viewUp ) * radius;
resultPosition = ( midpoint + ( signLeft * scaledLeft ) + ( signUp * scaledUp ) );
}
#endtemplate
/*
==================================================================================
CALC_POSITION_AUTOSPRITE1
==================================================================================
*/
#template CALC_POSITION_AUTOSPRITE2( resultPosition, viewOrg, midpoint, majorAxis, sign, edgeLen )
{
// Normals and tangents are stored as unsigned bytes - need to expand back to [-1,1] range
float s = sign * 2.0 - 1.0;
float3 axis = majorAxis * 2.0 - 1.0;
float len = edgeLen * 255.0 * s;
float3 dir = normalize( midpoint - viewOrg );
float3 minor = cross( axis, dir );
resultPosition = ( midpoint + len * minor );
}
#endtemplate
@@ -0,0 +1,77 @@
/*
==================================================================================
DEFERRED_LIGHTING
inout float3 color;
in float4 fragmentPosition;
in float4 windowPosition;
in float shadow;
==================================================================================
*/
#template DEFERRED_LIGHTING( color, fragmentPosition, windowPosition, shadow )
{
#if defined( PC ) && !defined( PC_D3D )
half4 viewDiffuse = texelFetch( $viewDiffuseMap, ivec2( fragmentPosition.xy ), 0 );
half4 viewNormal = texelFetch( $viewNormalMap, ivec2( fragmentPosition.xy ), 0 ) * 2.0 - 1.0;
#else
half4 viewDiffuse = tex2D( $viewDiffuseMap, windowPosition.xy );
half4 viewNormal = tex2D( $viewNormalMap, windowPosition.xy ) * 2.0 - 1.0;
#endif
half viewSpecular = viewDiffuse.w;
half viewPower = viewNormal.w;
half4 globalPosition;
globalPosition.x = dot4( windowPosition, $windowPosToGlobalX );
globalPosition.y = dot4( windowPosition, $windowPosToGlobalY );
globalPosition.z = dot4( windowPosition, $windowPosToGlobalZ );
globalPosition.w = dot4( windowPosition, $windowPosToGlobalW );
globalPosition.xyz /= globalPosition.w;
half3 light;
{
float4 lightTexCoord;
lightTexCoord.x = dot4( windowPosition, $windowPosToProjectedTexS );
lightTexCoord.y = dot4( windowPosition, $windowPosToProjectedTexT );
lightTexCoord.z = dot4( windowPosition, $windowPosToProjectedTexR );
lightTexCoord.w = dot4( windowPosition, $windowPosToProjectedTexQ );
lightTexCoord.xyz /= lightTexCoord.w;
half4 lpm = h4tex2D( $lightProjectMap, lightTexCoord.xy );
half4 lfm = h4tex2D( $lightFalloffMap, float2( lightTexCoord.z, 0.5 ) );
half3 toLight = normalize( $globalLightOrigin.xyz - globalPosition.xyz );
light = $lightColor.xyz * lpm.xyz * lfm.xyz;
light *= _float3( dot3( toLight, viewNormal.xyz ) );
light *= shadow;
}
half3 diffuse;
{
diffuse = viewDiffuse.xyz * $newDiffuseScale.xyz * 2.0;
}
half3 specular;
{
half3 toViewer = normalize( $globalViewOrigin.xyz - globalPosition.xyz );
// The reflection vector = 2 * N * ( N . V ) - V
half4 reflection;
reflection.xyz = ( 2.0 * viewNormal.xyz * dot3( viewNormal.xyz, toViewer ) ) - toViewer;
// Power factor is stored as 0.0 - 1.0 while we want a 0 | 1 | 2 | 3 mip value.
// The artists really prefer white to be shiny instead of dull, so invert it here.
// We could probably skip the floor, but I am wary of hardware / api rounding.
reflection.w = floor( ( 1.0 - viewPower ) * 4.0 + $newPowerScale.x );
half3 envColor = texCUBElod( $dynamicEnvMap, reflection ).xyz;
specular = envColor * viewSpecular * $newSpecularScale.xyz;
}
color.xyz = light * ( diffuse + specular );
}
#endtemplate
@@ -0,0 +1,179 @@
/*
==================================================================================
CALC_GORE_VERTEX
==================================================================================
*/
#template CALC_GORE_VERTEX( woundPos1, woundPos2 )
{
// Convert back from 16 bit vertex elements.
float4 vertexPos = vertex.position * $vertexXYZScale + $vertexXYZBias;
float3 wound1LocalPos = $wound1Pos.xyz - vertexPos.xyz;
float3 wound1LocalSpace;
wound1LocalSpace.x = dot( $wound1dirX.xyz, wound1LocalPos.xyz );
wound1LocalSpace.y = dot( $wound1dirY.xyz, wound1LocalPos.xyz );
wound1LocalSpace.z = dot( $wound1dirZ.xyz, wound1LocalPos.xyz );
float3 wound1Local = wound1LocalSpace / $wound1Size.xyz;
woundPos1.xy = wound1Local.xy + _float2( 0.5 );
woundPos1.z = 1.0 - abs( wound1Local.z );
woundPos1.w = 0.0;
float wound3A = ( length( ( $wound3PosA.xyz - vertexPos.xyz ) * $wound3PosA.w ) - 1.0f );
float wound3B = ( length( ( $wound3PosB.xyz - vertexPos.xyz ) * $wound3PosB.w ) - 1.0f );
float wound3C = ( length( ( $wound3PosC.xyz - vertexPos.xyz ) * $wound3PosC.w ) - 1.0f );
float wound3D = ( length( ( $wound3PosD.xyz - vertexPos.xyz ) * $wound3PosD.w ) - 1.0f );
float wound3E = ( length( ( $wound3PosE.xyz - vertexPos.xyz ) * $wound3PosE.w ) - 1.0f );
woundPos2.w = min( wound3A, wound3B );
woundPos2.w = min( woundPos2.w, wound3C );
woundPos2.w = min( woundPos2.w, wound3D );
woundPos2.w = min( woundPos2.w, wound3E );
float maskInfo = saturate( 1.0f - ( woundPos2.w * 0.2 ) );
maskInfo *= maskInfo * maskInfo;
}
#endtemplate
/*
==================================================================================
OCCLUDER_GORE_CLIP
==================================================================================
*/
#template OCCLUDER_GORE_CLIP( woundPos1, woundPos2 )
{
// gore wound 1
half4 woundMap1 = tex2D( $woundTexture, saturate( woundPos1.xy ) );
woundMap1 *= $wound1RGBA;
woundMap1 = woundMap1.xxxx + woundMap1.yyyy + woundMap1.zzzz + woundMap1.wwww;
woundMap1 = 1.0 - ( 1.0 - woundMap1 ) * ( saturate( woundPos1.z * half4( 1.0, 1.0 ,1.0 , 5.0 ) ) ) * $wound1Size.w;
woundMap1.x = saturate( ( woundMap1.x - 0.25 ) * 1.33 );
// gore wound 2
half4 woundMap2 = tex2D( $woundTexture, saturate( woundPos2.xy ) );
woundMap2 *= $wound2RGBA;
woundMap2 = woundMap2.xxxx + woundMap2.yyyy + woundMap2.zzzz + woundMap2.wwww;
woundMap2 = 1.0 - ( 1.0 - woundMap2 ) * ( saturate( woundPos2.z * half4( 1.0 , 1.0 ,1.0 ,5.0 ) ) ) * $wound2Size.w; // Photoshop screen blend
woundMap2.x = saturate( ( woundMap2.x - 0.25 ) * 1.33 );
// gore decal texture
// half4 woundMap3 = tex2D( $woundTexture, fragment.htexcoord0.xy * 2.0 ).wwww;
// woundMap3.xyz = woundMap3.xyz + _half3( 1.0 - woundPos1.w ) - _half3( woundPos1.w );
// woundMap3.w = saturate( ( 1.0 - ( 1.0 - woundMap3.w ) * 0.2 ) - woundPos1.w );
// float woundMask = min( min ( woundMap1.w, woundMap2.w ), woundMap3.w );
float woundMask = min( woundMap1.w, woundMap2.w );
woundMask = 1.0 -( ( 1.0 - woundMask ) * $woundClip.x );
clip( woundMask - 0.2 );
}
#endtemplate
/*
==================================================================================
APPLY_GORE_WOUNDS
==================================================================================
*/
#template APPLY_GORE_WOUNDS( diffuse, woundPos1, woundPos2, specularScale, skinMap )
{
// gore wound 1
half4 woundMap1 = tex2D( $woundClipTexture, saturate( woundPos1.xy ) );
woundMap1 *= $wound1RGBA;
woundMap1 = woundMap1.xxxx + woundMap1.yyyy + woundMap1.zzzz + woundMap1.wwww;
woundMap1 = 1.0f - ( 1.0f - woundMap1 ) * ( saturate( woundPos1.z * half4( 1.0f, 1.0f, 1.0f, 5.0f ) ) ) * $wound1Size.w;
woundMap1.x = saturate( ( woundMap1.x - 0.25 ) * 1.33 );
// gore decal texture
half4 woundMap3 = tex2D( $woundClipTexture, fragment.htexcoord7.xy ).wwww;
woundMap3.xyz = woundMap3.xyz + _half3( 1.0 - woundPos2.w ) - _half3( woundPos2.w );
woundMap3.w = woundPos2.w + ( woundMap3.w - 0.5f ) * 0.1f;
float woundMask = min ( woundMap1.w, woundMap3.w );
woundMask = 1.0f - ( ( 1.0f - woundMask ) * $woundClip.x );
clip( woundMask - 0.2f );
half3 woundComp = woundMap3.xyz;
woundComp = min( woundComp, woundMap1.xxx );
woundComp = saturate( woundComp );
// now just color the grayscale image by our chosen blood color - right now hardcoded to ( 0.3, 0.2, 0.1 );
woundComp = _float3( 1.0 ) - ( ( _float3( 1.0 ) - woundComp ) * ( _float3( 1.0 ) - float3( 0.3, 0.15, 0.1 ) ) );
woundComp *= woundComp * woundComp;
// now apply to diffuse - done!
diffuse.xyz *= woundComp.xyz;
}
#endtemplate
/*
==================================================================================
APPLY_GORE_COLOR
==================================================================================
*/
#template APPLY_GORE_COLOR( inColor )
{
diffuse.xyz *= _half3( 1.0 ) - ( _half3( inColor ) * half3( 0.7f, 0.85f, 0.9f ) );
}
#endtemplate
/*
==================================================================================
CALC_GORE_CLIP_SPHERES
==================================================================================
*/
#template CALC_GORE_CLIP_SPHERES( clipInfo )
{
float3 vertexPos = vertex.position.xyz;
clipInfo = _half4( 0 );
float wound3A = ( length( ( $wound3PosA.xyz - vertexPos.xyz ) * $wound3PosA.w ) - 1.0f );
float wound3B = ( length( ( $wound3PosB.xyz - vertexPos.xyz ) * $wound3PosB.w ) - 1.0f );
float wound3C = ( length( ( $wound3PosC.xyz - vertexPos.xyz ) * $wound3PosC.w ) - 1.0f );
float wound3D = ( length( ( $wound3PosD.xyz - vertexPos.xyz ) * $wound3PosD.w ) - 1.0f );
float wound3E = ( length( ( $wound3PosE.xyz - vertexPos.xyz ) * $wound3PosE.w ) - 1.0f );
float wound3F = ( length( ( $wound3PosF.xyz - vertexPos.xyz ) * $wound3PosF.w ) - 1.0f );
float wound3G = ( length( ( $wound3PosG.xyz - vertexPos.xyz ) * $wound3PosG.w ) - 1.0f );
float wound3H = ( length( ( $wound3PosH.xyz - vertexPos.xyz ) * $wound3PosH.w ) - 1.0f );
float wound3I = ( length( ( $wound3PosI.xyz - vertexPos.xyz ) * $wound3PosI.w ) - 1.0f );
float wound3J = ( length( ( $wound3PosJ.xyz - vertexPos.xyz ) * $wound3PosJ.w ) - 1.0f );
float3 ellipsoid;
float3 localPos = vertexPos.xyz - float3( $woundEllipsoidX.w, $woundEllipsoidY.w, $woundEllipsoidZ.w );
ellipsoid.x = dot( $woundEllipsoidX.xyz, localPos.xyz );
ellipsoid.y = dot( $woundEllipsoidY.xyz, localPos.xyz );
ellipsoid.z = dot( $woundEllipsoidZ.xyz, localPos.xyz );
float distToEllipsoid = length( ellipsoid ) - 1.0f;
clipInfo.w = min( wound3A, wound3B );
clipInfo.w = min( clipInfo.w, wound3C );
clipInfo.w = min( clipInfo.w, wound3D );
clipInfo.w = min( clipInfo.w, wound3E );
clipInfo.w = min( clipInfo.w, wound3F );
clipInfo.w = min( clipInfo.w, wound3G );
clipInfo.w = min( clipInfo.w, wound3H );
clipInfo.w = min( clipInfo.w, distToEllipsoid );
clipInfo.z = min( min( wound3I, wound3J ), clipInfo.w );
}
#endtemplate
/*
==================================================================================
APPLY_GORE_CLIP_SPHERES
==================================================================================
*/
#template APPLY_GORE_CLIP_SPHERES( woundClip, woundMap )
{
float clipValue = woundClip + ( woundMap.w - 0.5 ) * 0.1;
//-- dissolve effect
//if ( $modelFade.x < 1.0f ) {
// float4 mask = tex2D( $impDissolveTexture, fragment.texcoord7.xy );
// float dissolve = 1.0f - $modelFade.x;
// float dMask = mask.x - 0.01 - ( dissolve );
// clipValue = min( clipValue, dMask );
//}
//-- dissolve effect
clip( clipValue );
}
#endtemplate
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,40 @@
/*
==================================================================================
Equations to convert color values to luminance values using various ITU standards.
==================================================================================
*/
/*
==================================================================================
ITU HDR standard BT-709-5
EY? = 0.2126 ER? + 0.7152 EG? + 0.0722 EB
www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.709-5-200204-I!!PDF-E.pdf
int float colorRGB;
out float luminance;
==================================================================================
*/
#template Luminance_BT709( luminance, colorRGB )
{
const float3 ituBT709 = float3( 0.2126, 0.7152, 0.0722 );
lumiancne = dot( colorRGB, ituBT709 );
}
#endtemplate
/*
==================================================================================
ITU HDR standard BT-601-6
EY ? = 0.299 ER ? + 0.587 EG ? + 0.114 EB
www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-6-200701-S!!PDF-E.pdf
int float colorRGB;
out float luminance;
==================================================================================
*/
#template Luminance_BT601( luminance, colorRGB )
{
const float3 ituBT601 = float3( 0.299, 0.587, 0.114 );
luminance = dot( colorRGB, ituBT601 );
}
#endtemplate
@@ -0,0 +1,191 @@
/*
==================================================================================
SAMPLE_SHADOW_BUFFER_PCF
in float4 shadowTexCoord;
out float shadow;
==================================================================================
*/
#template SAMPLE_SHADOW_BUFFER_PCF( shadow, shadowTexCoord )
{
#if defined( XBOX )
// The Xbox 360 does not implement percentage-closer-filtering (PCF) in hardware.
// Instead the following implements bilinear PCF between four point samples.
float3 texCoord = shadowTexCoord;
float2 texelXY = texCoord.xy * $shadowBufferResolution.x - _float2( 0.5 );
float2 floorXY = floor( texelXY );
float2 fracXY = texelXY - floorXY;
float step = $shadowBufferResolution.y;
float2 baseXY = ( floorXY + _float2( 0.5 ) ) * $shadowBufferResolution.y;
float4 samples;
samples.x = tex2D( $lightDepthMap, baseXY + float2( 0*step, 0*step ) ).x;
samples.y = tex2D( $lightDepthMap, baseXY + float2( 1*step, 0*step ) ).x;
samples.z = tex2D( $lightDepthMap, baseXY + float2( 1*step, 1*step ) ).x;
samples.w = tex2D( $lightDepthMap, baseXY + float2( 0*step, 1*step ) ).x;
float4 pcf = float4( greaterThanEqual( ( _float4( 1.0 ) - samples ), texCoord.zzzz ) );
float4 weights;
weights.x = ( 1.0 - fracXY.x ) * ( 1.0 - fracXY.y );
weights.y = ( fracXY.x ) * ( 1.0 - fracXY.y );
weights.z = ( fracXY.x ) * ( fracXY.y );
weights.w = ( 1.0 - fracXY.x ) * ( fracXY.y );
shadow = dot4( pcf, weights );
#else
shadow = shadow2Ddepth( $lightDepthCompareMap, shadowTexCoord );
#endif
}
#endtemplate
/*
==================================================================================
SAMPLE_SHADOW_BUFFER_4ROOKS_PCF
in float4 shadowTexCoord;
out float shadow;
==================================================================================
*/
#template SAMPLE_SHADOW_BUFFER_4ROOKS_PCF( shadow, shadowTexCoord )
{
float s = $shadowBufferResolution.y * 2.0;
float4 shadow4;
SAMPLE_SHADOW_BUFFER_PCF( shadow4.x, shadowTexCoord.xyz + s * float3( -0.375, -0.125, 0 ) );
SAMPLE_SHADOW_BUFFER_PCF( shadow4.y, shadowTexCoord.xyz + s * float3( -0.125, 0.375, 0 ) );
SAMPLE_SHADOW_BUFFER_PCF( shadow4.z, shadowTexCoord.xyz + s * float3( 0.125, -0.375, 0 ) );
SAMPLE_SHADOW_BUFFER_PCF( shadow4.w, shadowTexCoord.xyz + s * float3( 0.375, 0.125, 0 ) );
shadow = dot( shadow4, _float4( 0.25 ) );
}
#endtemplate
/*
==================================================================================
SAMPLE_VARIANCE_SHADOW_MAP
in float4 shadowTexCoord;
out float shadow;
$varianceShadowMapSettings.x = minimumVariance
$varianceShadowMapSettings.y = deltaScale
$varianceShadowMapSettings.z = bleedReduction
$varianceShadowMapSettings.w = 1.0 / ( 1.0 - bleedReduction )
==================================================================================
*/
#template SAMPLE_VARIANCE_SHADOW_MAP( shadow, shadowTexCoord )
{
// Fetch the moments.
float2 moments = tex2D( $lightDepthVarianceMap, shadowTexCoord.xy ).xy;
// Compute variance.
float variance = moments.y - ( moments.x * moments.x );
variance = max( variance, $varianceShadowMapSettings.x );
// Compute probabilistic upper bound.
float d = $varianceShadowMapSettings.y * saturate( shadowTexCoord.z - moments.x );
float p_max = saturate( variance / ( variance + d * d ) );
// Remove the [0, bleedReduction] tail and linearly rescale (bleedReduction, 1].
shadow = saturate( ( p_max - $varianceShadowMapSettings.z ) * $varianceShadowMapSettings.w );
}
#endtemplate
/*
==================================================================================
SAMPLE_POINT_LIGHT_SHADOW
in float4 shadowTexCoord;
out float shadow;
==================================================================================
*/
#template SAMPLE_POINT_LIGHT_SHADOW( shadow, shadowTexCoord )
{
// calculate the maximum absolute shadow texture coordinate
float3 absTexCoord = abs( shadowTexCoord.xyz );
float3 maxTexCoord = max( absTexCoord.xyz, max( absTexCoord.yzx, absTexCoord.zxy ) );
// create a vector with a 1.0 for the first largest absolute component and 0.0 for the other components
float4 axis;
axis.xyz = float3( greaterThanEqual( absTexCoord, maxTexCoord ) ); // set 1.0 for any component equal to the max
axis.yz = saturate( axis.yz - axis.xx - axis.xy ); // make sure only one component is set to 1.0
axis.w = 0.0;
// rotate the shadow texture coordinate from one of the cube sides to the flat shadow buffer
float4 rotate = axis.yxxy + axis.zwzw;
float4 flatTexCoord;
flatTexCoord.x = dot( rotate.xy, shadowTexCoord.xz );
flatTexCoord.y = dot( rotate.zw, shadowTexCoord.yz );
flatTexCoord.z = -maxTexCoord.x;
flatTexCoord.w = shadowTexCoord.w;
// calculate the bias for the shadow buffer sub-image that corresponds to this axis
float sBias = 0.5 + dot( axis.xyz, float3( greaterThanEqual( float3( 0, 0, 0 ), shadowTexCoord.xyz ) ) );
float tBias = 0.5 + dot( axis.xyz, float3( 0, 1, 2 ) );
float4 faceTexCoord;
faceTexCoord.x = dot4( flatTexCoord, $shadowProjectionS + sBias * $shadowProjectionQ );
faceTexCoord.y = dot4( flatTexCoord, $shadowProjectionT + tBias * $shadowProjectionQ );
faceTexCoord.z = dot4( flatTexCoord, $shadowProjectionR );
faceTexCoord.w = dot4( flatTexCoord, $shadowProjectionQ );
faceTexCoord.xyz /= faceTexCoord.w;
faceTexCoord.xy *= $shadowBufferResolution.z;
SAMPLE_SHADOW_BUFFER_4ROOKS_PCF( shadow, faceTexCoord );
}
#endtemplate
/*
==================================================================================
SAMPLE_SPOT_LIGHT_SHADOW
in float4 shadowTexCoord;
out float shadow;
==================================================================================
*/
#template SAMPLE_SPOT_LIGHT_SHADOW( shadow, shadowTexCoord )
{
float3 texCoord = shadowTexCoord.xyz / shadowTexCoord.w;
SAMPLE_SHADOW_BUFFER_4ROOKS_PCF( shadow, texCoord );
}
#endtemplate
/*
==================================================================================
SAMPLE_PARALLEL_LIGHT_SHADOW
in float4 shadowTexCoord;
in float viewZ;
out float shadow;
==================================================================================
*/
#template SAMPLE_PARALLEL_LIGHT_SHADOW( shadow, shadowTexCoord, viewZ )
{
float3 texCoord = shadowTexCoord.xyz / shadowTexCoord.w;
float sliceLOD = log2( max( 1.0, viewZ * $parallelLightSliceScale.x ) ) * $parallelLightSliceScale.z;
float sliceLODi = floor( sliceLOD );
float2 slice = min( float2( 3.0, 3.0 ), float2( sliceLODi, sliceLODi ) + float2( 0.0, 1.0 ) );
float2 stScale = exp2( - slice * $parallelLightSliceScale.y );
float4 stBias;
stBias.xy = 0.25 + frac( slice * 0.5 );
stBias.zw = 0.25 + floor( slice * 0.5 ) * 0.5;
float4 sliceTexCoords = texCoord.xxyy * stScale.xyxy + stBias;
float3 slice1TexCoord = float3( sliceTexCoords.x, sliceTexCoords.z, texCoord.z );
float3 slice2TexCoord = float3( sliceTexCoords.y, sliceTexCoords.w, texCoord.z );
float fraction = saturate( ( slice.y - sliceLOD ) * $parallelLightSliceScale.w );
float shadow1;
SAMPLE_SHADOW_BUFFER_4ROOKS_PCF( shadow1, slice1TexCoord );
float shadow2;
SAMPLE_SHADOW_BUFFER_4ROOKS_PCF( shadow2, slice2TexCoord );
shadow = lerp( shadow2, shadow1, fraction );
}
#endtemplate
@@ -0,0 +1,204 @@
/*
==================================================================================
FETCH_UNIQUE
==================================================================================
*/
#template FETCH_UNIQUE( sampleSpecular, sampleYCoCg, sampleNormal )
{
float3 physCoord = UniqueVirtualToPhysical( fragment.texcoord0.xy );
#ifdef USE_VIRTUAL_ANISO_FOOTPRINT
float2 dx = ddx( fragment.texcoord0.xy ) * physCoord.z;
float2 dy = ddy( fragment.texcoord0.xy ) * physCoord.z;
sampleSpecular = texPhys( $physicalUniquePagesMap0, physCoord.xy, dx, dy );
sampleYCoCg = texPhys( $physicalUniquePagesMap1, physCoord.xy, dx, dy );
sampleNormal = texPhys( $physicalUniquePagesMap2, physCoord.xy, dx, dy );
#else
sampleSpecular = h4texPhys( $physicalUniquePagesMap0, physCoord.xy );
sampleYCoCg = h4texPhys( $physicalUniquePagesMap1, physCoord.xy );
sampleNormal = h4texPhys( $physicalUniquePagesMap2, physCoord.xy );
#endif
}
#endtemplate
/*
==================================================================================
FETCH_UNIQUE_BLEND
uses fragment.texcoord0;
out half4 sampleSpecular;
out half4 sampleYCoCg;
out half4 sampleNormal;
out half2 feedbackTexCoord;
out half morphScale;
==================================================================================
*/
#template FETCH_UNIQUE_BLEND( sampleSpecular, sampleYCoCg, sampleNormal, feedbackTexCoord, morphScale )
{
float4 texCoord = fragment.texcoord0;
float3 physCoord = UniqueVirtualToPhysical( texCoord.xy );
#ifdef USE_VIRTUAL_ANISO_FOOTPRINT
float2 dx = ddx( texCoord.xy ) * physCoord.z;
float2 dy = ddy( texCoord.xy ) * physCoord.z;
sampleSpecular = texPhys( $physicalUniquePagesMap0, physCoord.xy, dx, dy );
sampleYCoCg = texPhys( $physicalUniquePagesMap1, physCoord.xy, dx, dy );
sampleNormal = texPhys( $physicalUniquePagesMap2, physCoord.xy, dx, dy );
#else
sampleSpecular = texPhys( $physicalUniquePagesMap0, physCoord.xy );
sampleYCoCg = texPhys( $physicalUniquePagesMap1, physCoord.xy );
sampleNormal = texPhys( $physicalUniquePagesMap2, physCoord.xy );
#endif
feedbackTexCoord = texCoord.xy;
/* blend in another texture based on the morph map */
{
float3 physCoord = UniqueVirtualToPhysical( texCoord.zw );
#ifdef USE_VIRTUAL_ANISO_FOOTPRINT
float2 dx = ddx( texCoord.zw ) * physCoord.z;
float2 dy = ddy( texCoord.zw ) * physCoord.z;
float4 sampleSpecular2 = texPhys( $physicalUniquePagesMap0, physCoord.xy, dx, dy );
float4 sampleYCoCg2 = texPhys( $physicalUniquePagesMap1, physCoord.xy, dx, dy );
float4 sampleNormal2 = texPhys( $physicalUniquePagesMap2, physCoord.xy, dx, dy );
#else
float4 sampleSpecular2 = texPhys( $physicalUniquePagesMap0, physCoord.xy );
float4 sampleYCoCg2 = texPhys( $physicalUniquePagesMap1, physCoord.xy );
float4 sampleNormal2 = texPhys( $physicalUniquePagesMap2, physCoord.xy );
#endif
sampleSpecular = lerp( sampleSpecular, sampleSpecular2, morphScale );
sampleYCoCg = lerp( sampleYCoCg, sampleYCoCg2, morphScale );
sampleNormal = lerp( sampleNormal, sampleNormal2, morphScale );
float2 fp = fragment.position.xy * $positionToFeedback.zw;
float2 xy = frac( fp ) - 0.5;
feedbackTexCoord = ( xy.x * xy.y < 0.0 ) ? texCoord.xy : texCoord.zw;
}
}
#endtemplate
/*
==================================================================================
FETCH_UNIQUE_YCOCG
==================================================================================
*/
#template FETCH_UNIQUE_YCOCG( sampleYCoCg )
{
float3 physCoord = UniqueVirtualToPhysical( fragment.texcoord0.xy );
#ifdef USE_VIRTUAL_ANISO_FOOTPRINT
float2 dx = ddx( fragment.texcoord0.xy ) * physCoord.z;
float2 dy = ddy( fragment.texcoord0.xy ) * physCoord.z;
sampleYCoCg = texPhys( $physicalUniquePagesMap1, physCoord.xy, dx, dy );
#else
sampleYCoCg = texPhys( $physicalUniquePagesMap1, physCoord.xy );
#endif
}
#endtemplate
/*
==================================================================================
FETCH_DIFFUSE_ONLY
==================================================================================
*/
#template FETCH_DIFFUSE_ONLY( sampleYCoCg )
{
float3 physCoord = UniqueDiffuseOnlyVirtualToPhysical( fragment.texcoord0.xy );
#ifdef USE_VIRTUAL_ANISO_FOOTPRINT
float2 dx = ddx( fragment.texcoord0.xy ) * physCoord.z;
float2 dy = ddy( fragment.texcoord0.xy ) * physCoord.z;
sampleYCoCg = texPhys( $physicalUniqueDiffuseOnlyPagesMap1, physCoord.xy, dx, dy );
#else
sampleYCoCg = texPhys( $physicalUniqueDiffuseOnlyPagesMap1, physCoord.xy );
#endif
}
#endtemplate
/*
==================================================================================
FETCH_DIFFUSE_ONLY2
==================================================================================
*/
#template FETCH_DIFFUSE_ONLY2( sampleYCoCg )
{
float3 physCoord = UniqueDiffuseOnly2VirtualToPhysical( fragment.texcoord0.xy );
#ifdef USE_VIRTUAL_ANISO_FOOTPRINT
float2 dx = ddx( fragment.texcoord0.xy ) * physCoord.z;
float2 dy = ddy( fragment.texcoord0.xy ) * physCoord.z;
sampleYCoCg = texPhys( $physicalUniqueDiffuseOnly2PagesMap1, physCoord.xy, dx, dy );
#else
sampleYCoCg = texPhys( $physicalUniqueDiffuseOnly2PagesMap1, physCoord.xy );
#endif
}
#endtemplate
/*
==================================================================================
CALC_DIFFUSE_RGB
==================================================================================
*/
#template CALC_DIFFUSE_RGB( diffuse, sampleYCoCg )
{
sampleYCoCg.z = ( sampleYCoCg.z * 31.875 ) + 1.0; /* z = z * 255.0/8.0 + 1.0 */
sampleYCoCg.z = 1.0 / sampleYCoCg.z;
sampleYCoCg.xy *= sampleYCoCg.z;
diffuse.x = dot4( sampleYCoCg, matrixCoCg1YtoRGB1X );
diffuse.y = dot4( sampleYCoCg, matrixCoCg1YtoRGB1Y );
diffuse.z = dot4( sampleYCoCg, matrixCoCg1YtoRGB1Z );
diffuse.w = 0.5; // how much to accept dim-shadows
diffuse.xyz *= $newDiffuseScale.xyz;
}
#endtemplate
/*
==================================================================================
APPLY_SPECULAR
==================================================================================
*/
#template APPLY_SPECULAR( color, sampleSpecular, sampleNormal, localToGlobalX, localToGlobalY, localToGlobalZ, viewOriginToFragment )
{
/* Note that the optimized derivation of the localNormal below results */
/* in a vector that is half-unit length! */
half3 localNormal;
localNormal.xy = sampleNormal.wy - 0.5;
localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
/* transform the normal into ambient map space */
half3 globalNormal;
globalNormal.x = dot3( localNormal, localToGlobalX );
globalNormal.y = dot3( localNormal, localToGlobalY );
globalNormal.z = dot3( localNormal, localToGlobalZ );
globalNormal = normalize( globalNormal );
/* calculate the specular reflection vector from viewer and globalNormal */
half4 reflection;
reflection.xyz = viewOriginToFragment - ( globalNormal * dot3( viewOriginToFragment, globalNormal ) * 2.0 );
/* Power factor is stored in sampleNormal.x as 0.0 - 1.0 */
/* We want a 0 | 1 | 2 | 3 mip value. */
/* The artists really prefer white to be shiny instead of dull, so invert it here. */
/* We could probably skip the floor, but I am wary of hardware / api rounding. */
reflection.w = floor( ( 1.0 - sampleNormal.x ) * 4.0 + $newPowerScale.x );
half3 envColor = texCUBElod( $dynamicEnvMap, reflection ).xyz;
half3 specular = sampleSpecular.xyz * 8.0 / ( sampleNormal.z * 255.0 + 8.0 );
/* modulate by the environment mask map (specular channel) */
color.xyz += envColor * specular * $newSpecularScale.xyz;
}
#endtemplate
@@ -0,0 +1,752 @@
/*
==================================================================================
CALC_TEXCOORDS
uses vertex.texcoord0;
out float4 texcoords;
==================================================================================
*/
#template CALC_TEXCOORDS( texcoords )
{
// base coordinates modified by stScaleBias for 16 bit vertex elements
texcoords = ( vertex.texcoord0.xy * $vertexStScaleBias.xy + $vertexStScaleBias.zw ).xyxy;
}
#endtemplate
/*
==================================================================================
CALC_TEXCOORDS_BLEND
uses vertex.texcoord0;
out float4 texcoords;
==================================================================================
*/
#template CALC_TEXCOORDS_BLEND( texcoords )
{
// base coordinates modified by stScaleBias for 16 bit vertex elements
texcoords = ( vertex.texcoord0.xyxy * $vertexStScaleBias.xyxy + $vertexStScaleBias.zwzw ) + skinOffsets.xyzw;
}
#endtemplate
/*
==================================================================================
CALC_POSITION
uses vertex.position;
out float4 resultPosition;
==================================================================================
*/
#template CALC_POSITION( resultPosition )
{
// Convert back from 16 bit vertex elements.
float4 localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
resultPosition.x = dot4( localPosition, $mvpMatrixX );
resultPosition.y = dot4( localPosition, $mvpMatrixY );
resultPosition.z = dot4( localPosition, $mvpMatrixZ );
resultPosition.w = dot4( localPosition, $mvpMatrixW );
}
#endtemplate
/*
==================================================================================
CALC_MUZZLE_FLASH_VECTOR
uses MFOffset;
out MFVector;
==================================================================================
*/
#template CALC_MUZZLE_FLASH_VECTOR( MFOffset, MFVector )
{
//float3 globalPosition = _float4( 0.0 );
//globalPosition.x = dot4( position, $modelMatrixX );
//globalPosition.y = dot4( position, $modelMatrixY );
//globalPosition.z = dot4( position, $modelMatrixZ );
float3 globalMFOffset = _float3( 0.0 );
//float3 altGlobalViewFwd = cross( $globalViewLeft.xyz, $globalViewUp.xyz );
//globalMFOffset.xyz = altGlobalViewFwd.xyz * _float3( MFOffset.x );
globalMFOffset.xyz = $globalViewFwd.xyz * _float3( MFOffset.x );
globalMFOffset.xyz += $globalViewLeft.xyz * _float3( MFOffset.y );
globalMFOffset.xyz += $globalViewUp.xyz * _float3( MFOffset.z );
//float3 globalMFPosition = $globalViewOrigin.xyz + globalMFOffset;
MFVector.xyz = normalize( globalMFOffset );
//MFVector.xyz = normalize( $globalViewFwd.xyz );
MFVector.w = 1.0;
//float4 localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
//MFOffset = normalize( MFOffset - localPosition );
//MFVector.x = dot3( MFOffset, $modelMatrixX );
//MFVector.y = dot3( MFOffset, $modelMatrixY );
//MFVector.z = dot3( MFOffset, $modelMatrixZ );
//MFVector.w = 0.0;
}
#endtemplate
/*
==================================================================================
CALC_POSITION_NORMALS
uses vertex.position;
uses vertex.normal;
uses vertex.tangent;
out float4 resultPosition;
out float4 localToGlobalX;
out float4 localToGlobalY;
out float4 localToGlobalZ;
out float4 viewOriginToVertex;
==================================================================================
*/
#template CALC_POSITION_NORMALS( resultPosition, localToGlobalX, localToGlobalY, localToGlobalZ, viewOriginToVertex )
{
// Convert back from 16 bit vertex elements.
float4 localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
float4 normal = vertex.normal * 2.0 - 1.0;
float4 tangent = vertex.tangent * 2.0 - 1.0;
float3 bitangent = cross( normal.xyz, tangent.xyz ) * tangent.w;
resultPosition.x = dot4( localPosition, $mvpMatrixX );
resultPosition.y = dot4( localPosition, $mvpMatrixY );
resultPosition.z = dot4( localPosition, $mvpMatrixZ );
resultPosition.w = dot4( localPosition, $mvpMatrixW );
localToGlobalX.x = dot3( tangent, $modelMatrixX );
localToGlobalX.y = dot3( bitangent, $modelMatrixX );
localToGlobalX.z = dot3( normal, $modelMatrixX );
localToGlobalX.w = 0.0;
localToGlobalY.x = dot3( tangent, $modelMatrixY );
localToGlobalY.y = dot3( bitangent, $modelMatrixY );
localToGlobalY.z = dot3( normal, $modelMatrixY );
localToGlobalY.w = 0.0;
localToGlobalZ.x = dot3( tangent, $modelMatrixZ );
localToGlobalZ.y = dot3( bitangent, $modelMatrixZ );
localToGlobalZ.z = dot3( normal, $modelMatrixZ );
localToGlobalZ.w = 0.0;
viewOriginToVertex.x = dot4( localPosition, $modelMatrixX );
viewOriginToVertex.y = dot4( localPosition, $modelMatrixY );
viewOriginToVertex.z = dot4( localPosition, $modelMatrixZ );
viewOriginToVertex.xyz -= $globalViewOrigin.xyz;
viewOriginToVertex.w = 0.0;
}
#endtemplate
/*
==================================================================================
CALC_SKINNED_POSITIONS
uses vertex.position;
out float4 localPosition;
out float4 resultPosition;
==================================================================================
*/
// CALC_SKINNED_POSITIONS is a reduced form of CALC_SKINNED_POSITIONS_NORMALS
#template CALC_SKINNED_POSITIONS( localPosition, resultPosition )
{
// Convert back from 16 bit vertex elements.
localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
#if defined( XBOX )
if ( bHardwareSkinning ) {
float4 vertexPosition = localPosition;
if ( bHardwareMorphing ) {
#if 0
// Fetch the morph value with inline asm,
// so it only gets getched when bHardwareMorphing is
// enabled. If we just used vertex.morph.xyz, it would
// always be fetched, and gives streams of Pix warnings
// when the stream buffer is bound to NULL.
float4 vertexMorph;
int index = vertex.index;
asm {
vfetch vertexMorph, index, color2
};
float3 morphVector = ( vertexMorph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertexMorph.w * 32.0f );
#else
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
#endif
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.a * 255.1;
asm {
vfetch matX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch matY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch matZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX *= w0;
matY *= w0;
matZ *= w0;
float4 tmatX, tmatY, tmatZ;
joint = vertex.color.b * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w1;
matY += tmatY * w1;
matZ += tmatZ * w1;
joint = vertex.color.g * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w2;
matY += tmatY * w2;
matZ += tmatZ * w2;
joint = vertex.color.r * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w3;
matY += tmatY * w3;
matZ += tmatZ * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
}
#elif defined( PS3 )
if ( hardwareSkinning ) {
float4 vertexPosition = localPosition;
if ( hardwareMorphing ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255.1 * 3;
matX = matrices[joint+0] * w0;
matY = matrices[joint+1] * w0;
matZ = matrices[joint+2] * w0;
joint = vertex.color.g * 255.1 * 3;
matX += matrices[joint+0] * w1;
matY += matrices[joint+1] * w1;
matZ += matrices[joint+2] * w1;
joint = vertex.color.b * 255.1 * 3;
matX += matrices[joint+0] * w2;
matY += matrices[joint+1] * w2;
matZ += matrices[joint+2] * w2;
joint = vertex.color.a * 255.1 * 3;
matX += matrices[joint+0] * w3;
matY += matrices[joint+1] * w3;
matZ += matrices[joint+2] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
}
#elif defined( PC_D3D )
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = localPosition;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
}
#elif defined( PC )
// apply vertex morphs
if ( hardwareSkinning.z != 0.0 ) {
localPosition += $vertexMorphScale.x * vertex.position1;
}
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = localPosition;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
}
#else
#error "unknown platform"
#endif
resultPosition.x = dot4( localPosition, $mvpMatrixX );
resultPosition.y = dot4( localPosition, $mvpMatrixY );
resultPosition.z = dot4( localPosition, $mvpMatrixZ );
resultPosition.w = dot4( localPosition, $mvpMatrixW );
}
#endtemplate
/*
==================================================================================
CALC_SKINNED_POSITIONS_NORMALS
uses vertex.position;
uses vertex.normal;
uses vertex.tangent;
out float4 localPosition;
out float4 resultPosition;
out float4 localToGlobalX;
out float4 localToGlobalY;
out float4 localToGlobalZ;
out float4 viewOriginToVertex;
==================================================================================
*/
#template CALC_PNT( position, normal, tangent )
{
// Convert back from 16 bit vertex elements.
position = vertex.position * $vertexXYZScale + $vertexXYZBias;
normal = vertex.normal * 2.0 - 1.0;
tangent = vertex.tangent * 2.0 - 1.0;
//float morphScale = 0.0f;
}
#endtemplate
// CALC_SKINNED_POSITIONS is a reduced form of CALC_SKINNED_POSITIONS_NORMALS
#template CALC_SKINNED_POSITIONS_NORMALS( localPosition, resultPosition, localToGlobalX, localToGlobalY, localToGlobalZ, viewOriginToVertex, position, normal, tangent, worldPosition )
{
// Convert back from 16 bit vertex elements.
//localPosition = vertex.position * $vertexXYZScale + $vertexXYZBias;
//float4 normal = vertex.normal * 2.0 - 1.0;
//float4 tangent = vertex.tangent * 2.0 - 1.0;
float morphScale = 0.0f;
localPosition = position;
#if defined( XBOX )
if ( bHardwareSkinning ) {
float4 vertexPosition = localPosition;
if ( bHardwareMorphing ) {
#if 0
// Fetch the morph value with inline asm,
// so it only gets getched when bHardwareMorphing is
// enabled. If we just used vertex.morph.xyz, it would
// always be fetched, and gives streams of Pix warnings
// when the stream buffer is bound to NULL.
float4 vertexMorph;
int index = vertex.index;
asm {
vfetch vertexMorph, index, color2
};
float3 morphVector = ( vertexMorph.xyz * 2 ) - 1;
morphScale = vertexMorph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
#else
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
#endif
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.a * 255.1;
asm {
vfetch matX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch matY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch matZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX *= w0;
matY *= w0;
matZ *= w0;
float4 tmatX, tmatY, tmatZ;
joint = vertex.color.b * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w1;
matY += tmatY * w1;
matZ += tmatZ * w1;
joint = vertex.color.g * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w2;
matY += tmatY * w2;
matZ += tmatZ * w2;
joint = vertex.color.r * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w3;
matY += tmatY * w3;
matZ += tmatZ * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
}
#elif defined( PS3 )
if ( hardwareSkinning ) {
float4 vertexPosition = localPosition;
if ( hardwareMorphing ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255.1 * 3;
matX = matrices[joint+0] * w0;
matY = matrices[joint+1] * w0;
matZ = matrices[joint+2] * w0;
joint = vertex.color.g * 255.1 * 3;
matX += matrices[joint+0] * w1;
matY += matrices[joint+1] * w1;
matZ += matrices[joint+2] * w1;
joint = vertex.color.b * 255.1 * 3;
matX += matrices[joint+0] * w2;
matY += matrices[joint+1] * w2;
matZ += matrices[joint+2] * w2;
joint = vertex.color.a * 255.1 * 3;
matX += matrices[joint+0] * w3;
matY += matrices[joint+1] * w3;
matZ += matrices[joint+2] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
}
#elif defined( PC_D3D )
// FIXME_D3D
#elif defined( PC )
// apply vertex morphs
if ( hardwareSkinning.z != 0.0 ) {
localPosition += $vertexMorphScale.x * vertex.position1;
}
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = localPosition;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
localPosition.x = dot4( vertexPosition, matX );
localPosition.y = dot4( vertexPosition, matY );
localPosition.z = dot4( vertexPosition, matZ );
localPosition.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
}
#else
#error "unknown platform"
#endif
float3 bitangent = cross( normal.xyz, tangent.xyz ) * tangent.w;
position = localPosition;
// vertex position
resultPosition.x = dot4( localPosition, $mvpMatrixX );
resultPosition.y = dot4( localPosition, $mvpMatrixY );
resultPosition.z = dot4( localPosition, $mvpMatrixZ );
resultPosition.w = dot4( localPosition, $mvpMatrixW );
// transform matrix from vertex local space to world space
worldPosition.x = dot4( localPosition, $modelMatrixX );
worldPosition.y = dot4( localPosition, $modelMatrixY );
worldPosition.z = dot4( localPosition, $modelMatrixZ );
// transform matrix from vertex local space to world space
localToGlobalX.x = dot3( tangent, $modelMatrixX );
localToGlobalX.y = dot3( bitangent, $modelMatrixX );
localToGlobalX.z = dot3( normal, $modelMatrixX );
localToGlobalX.w = morphScale;
localToGlobalY.x = dot3( tangent, $modelMatrixY );
localToGlobalY.y = dot3( bitangent, $modelMatrixY );
localToGlobalY.z = dot3( normal, $modelMatrixY );
localToGlobalY.w = 0.0;
localToGlobalZ.x = dot3( tangent, $modelMatrixZ );
localToGlobalZ.y = dot3( bitangent, $modelMatrixZ );
localToGlobalZ.z = dot3( normal, $modelMatrixZ );
localToGlobalZ.w = 0.0;
// dir from the viewer to the vertex
viewOriginToVertex.x = dot4( localPosition, $modelMatrixX );
viewOriginToVertex.y = dot4( localPosition, $modelMatrixY );
viewOriginToVertex.z = dot4( localPosition, $modelMatrixZ );
viewOriginToVertex.xyz -= $globalViewOrigin.xyz;
viewOriginToVertex.w = 0.0;
}
#endtemplate
/*
==================================================================================
CALC_SKINNED_POSITION
uses vertex.position;
out float4 resultPosition;
==================================================================================
*/
#template CALC_SKINNED_POSITION( resultPosition )
{
float4 localPosition;
CALC_SKINNED_POSITIONS( localPosition, resultPosition );
}
#endtemplate
/*
==================================================================================
CALC_SKINNED_POSITIONS_NORMALS
uses vertex.position;
uses vertex.normal;
uses vertex.tangent;
out float4 resultPosition;
out float4 localToGlobalX;
out float4 localToGlobalY;
out float4 localToGlobalZ;
out float4 viewOriginToVertex;
==================================================================================
*/
#template CALC_SKINNED_POSITION_NORMALS( resultPosition, localToGlobalX, localToGlobalY, localToGlobalZ, viewOriginToVertex, position, normal, tangent, worldPosition )
{
float4 localPosition;
CALC_SKINNED_POSITIONS_NORMALS( localPosition, resultPosition, localToGlobalX, localToGlobalY, localToGlobalZ, viewOriginToVertex, position, normal, tangent, worldPosition );
}
#endtemplate
@@ -0,0 +1,970 @@
/*
==================================================================================
CALC_VMTR_TEXCOORD
uses fragment.texcoord0;
out half4 texCoord
==================================================================================
*/
#template CALC_VMTR_TEXCOORD( texCoord )
{
texCoord = fragment.texcoord0;
/*-------- non-wrapping virtual texture lookup ------------*/
BRANCH if ( $useVirtualMapping.x > 0 ) {
/* This is basically only for non pre-lit levels, and shouldn't be used often. */
/* This doesn't attempt to get the derivative correct at the frac crossing point. */
#ifdef VMTR_TEXCOORD_SKIP_FRAC
texCoord = texCoord * $virtualMapping.xyxy + $virtualMapping.zwzw;
#else
texCoord = frac( texCoord ) * $virtualMapping.xyxy + $virtualMapping.zwzw;
#endif
}
}
#endtemplate
/*
==================================================================================
FETCH_VMTR
uses fragment.texcoord0;
out half4 sampleSpecular;
out half4 sampleYCoCg;
out half4 sampleNormal;
out half2 feedbackTexCoord;
==================================================================================
*/
#template FETCH_VMTR( sampleSpecular, sampleYCoCg, sampleNormal, feedbackTexCoord )
{
float4 texCoord;
CALC_VMTR_TEXCOORD( texCoord );
float3 physCoord = VmtrVirtualToPhysical( texCoord.xy );
#ifdef USE_VIRTUAL_ANISO_FOOTPRINT
float2 dx = ddx( texCoord.xy ) * physCoord.z;
float2 dy = ddy( texCoord.xy ) * physCoord.z;
sampleSpecular = texPhys( $physicalVmtrPagesMap0, physCoord.xy, dx, dy );
sampleYCoCg = texPhys( $physicalVmtrPagesMap1, physCoord.xy, dx, dy );
sampleNormal = texPhys( $physicalVmtrPagesMap2, physCoord.xy, dx, dy );
#else
sampleSpecular = texPhys( $physicalVmtrPagesMap0, physCoord.xy );
sampleYCoCg = texPhys( $physicalVmtrPagesMap1, physCoord.xy );
sampleNormal = texPhys( $physicalVmtrPagesMap2, physCoord.xy );
#endif
feedbackTexCoord = texCoord.xy;
}
#endtemplate
/*
==================================================================================
FETCH_VMTR_BLEND
uses fragment.texcoord0;
out half4 sampleSpecular;
out half4 sampleYCoCg;
out half4 sampleNormal;
out half2 feedbackTexCoord;
in half morphScale;
==================================================================================
*/
#template FETCH_VMTR_BLEND( sampleSpecular, sampleYCoCg, sampleNormal, feedbackTexCoord, morphScale )
{
float4 texCoord;
CALC_VMTR_TEXCOORD( texCoord );
float3 physCoord = VmtrVirtualToPhysical( texCoord.xy );
#ifdef USE_VIRTUAL_ANISO_FOOTPRINT
float2 dx = ddx( texCoord.xy ) * physCoord.z;
float2 dy = ddy( texCoord.xy ) * physCoord.z;
sampleSpecular = texPhys( $physicalVmtrPagesMap0, physCoord.xy, dx, dy );
sampleYCoCg = texPhys( $physicalVmtrPagesMap1, physCoord.xy, dx, dy );
sampleNormal = texPhys( $physicalVmtrPagesMap2, physCoord.xy, dx, dy );
#else
sampleSpecular = texPhys( $physicalVmtrPagesMap0, physCoord.xy );
sampleYCoCg = texPhys( $physicalVmtrPagesMap1, physCoord.xy );
sampleNormal = texPhys( $physicalVmtrPagesMap2, physCoord.xy );
#endif
feedbackTexCoord = texCoord.xy;
/* blend in another texture based on the morph map */
BRANCH if ( $useSkinBlending.x > 0.0 ) {
float3 physCoord = VmtrVirtualToPhysical( texCoord.zw );
#ifdef USE_VIRTUAL_ANISO_FOOTPRINT
float2 dx = ddx( texCoord.zw ) * physCoord.z;
float2 dy = ddy( texCoord.zw ) * physCoord.z;
float4 sampleSpecular2 = texPhys( $physicalVmtrPagesMap0, physCoord.xy, dx, dy );
float4 sampleYCoCg2 = texPhys( $physicalVmtrPagesMap1, physCoord.xy, dx, dy );
float4 sampleNormal2 = texPhys( $physicalVmtrPagesMap2, physCoord.xy, dx, dy );
#else
float4 sampleSpecular2 = texPhys( $physicalVmtrPagesMap0, physCoord.xy );
float4 sampleYCoCg2 = texPhys( $physicalVmtrPagesMap1, physCoord.xy );
float4 sampleNormal2 = texPhys( $physicalVmtrPagesMap2, physCoord.xy );
#endif
sampleSpecular = lerp( sampleSpecular, sampleSpecular2, morphScale );
sampleYCoCg = lerp( sampleYCoCg, sampleYCoCg2, morphScale );
sampleNormal = lerp( sampleNormal, sampleNormal2, morphScale );
float2 fp = fragment.position.xy * $positionToFeedback.zw;
float2 xy = frac( fp ) - 0.5;
feedbackTexCoord = ( xy.x * xy.y < 0.0 ) ? texCoord.xy : texCoord.zw;
}
}
#endtemplate
/*
==================================================================================
CALC_VMTR_FEEDBACK
in half2 feedbackTexCoord;
out float4 feedback;
==================================================================================
*/
#template CALC_VMTR_FEEDBACK( feedback, feedbackTexCoord )
{
feedback = PackFeedback( CalculateFeedback( feedbackTexCoord, $virtualTextureFeedbackFloat, $physicalVmtrFilterParms ) );
}
#endtemplate
/*
==================================================================================
CALC_DIFFUSE_RGB
in half4 sampleYCoCg;
inout half4 diffuse;
==================================================================================
*/
#template CALC_DIFFUSE_RGB( diffuse, sampleYCoCg )
{
sampleYCoCg.z = ( sampleYCoCg.z * 31.875 ) + 1.0; /* z = z * 255.0/8.0 + 1.0 */
sampleYCoCg.z = 1.0 / sampleYCoCg.z;
sampleYCoCg.xy *= sampleYCoCg.z;
diffuse.x = dot4( sampleYCoCg, matrixCoCg1YtoRGB1X );
diffuse.y = dot4( sampleYCoCg, matrixCoCg1YtoRGB1Y );
diffuse.z = dot4( sampleYCoCg, matrixCoCg1YtoRGB1Z );
}
#endtemplate
/*
==================================================================================
CALC_SPECULAR_RGB
==================================================================================
*/
#template CALC_SPECULAR_RGB( specular, sampleSpecular, specularScale )
{
specular = sampleSpecular.xyz * 8.0 / ( specularScale * 255.0 + 8.0 );
specular += 0.001;
}
#endtemplate
/*
==================================================================================
CALC_LOCAL_NORMAL
==================================================================================
*/
#template CALC_LOCAL_NORMAL( localNormal, sampleNormal )
{
/* Note that the optimized derivation of the localNormal below results */
/* in a vector that is half-unit length! */
localNormal = sampleNormal.wyz - 0.5;
localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
}
#endtemplate
/*
==================================================================================
CALC_SMOOTH_NORMAL
==================================================================================
*/
#template CALC_SMOOTH_NORMAL( smoothNormal, localToGlobalX, localToGlobalY, localToGlobalZ )
{
smoothNormal.x = localToGlobalX.z;
smoothNormal.y = localToGlobalY.z;
smoothNormal.z = localToGlobalZ.z;
smoothNormal = normalize( smoothNormal );
}
#endtemplate
/*
==================================================================================
CALC_GLOBAL_NORMAL
==================================================================================
*/
#template CALC_GLOBAL_NORMAL( globalNormal, sampleNormal, localToGlobalX, localToGlobalY, localToGlobalZ )
{
/* Note that the optimized derivation of the localNormal below results */
/* in a vector that is half-unit length! */
half3 localNormal = sampleNormal.wyz - 0.5;
localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
/* transform the normal into ambient map space */
globalNormal.x = dot3( localNormal, localToGlobalX );
globalNormal.y = dot3( localNormal, localToGlobalY );
globalNormal.z = dot3( localNormal, localToGlobalZ );
globalNormal = normalize( globalNormal );
}
#endtemplate
/*
==================================================================================
CALC_GLOBAL_NORMAL_TWOSIDED
==================================================================================
*/
#template CALC_GLOBAL_NORMAL_TWOSIDED( globalNormal, sampleNormal, localToGlobalX, localToGlobalY, localToGlobalZ )
{
/* Note that the optimized derivation of the localNormal below results */
/* in a vector that is half-unit length! */
half3 localNormal = sampleNormal.wyz - 0.5;
localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );
/* flip the normal around if looking at the back side */
#if defined( XBOX )
if ( fragment.facing > 0 ) {
localNormal.z = -localNormal.z;
}
#elif defined( PS3 )
if ( fragment.face < 0 ) {
localNormal.z = -localNormal.z;
}
#elif defined( GLSL )
if ( !gl_FrontFacing ) {
localNormal.z = -localNormal.z;
}
#endif
/* transform the normal into ambient map space */
globalNormal.x = dot3( localNormal, localToGlobalX );
globalNormal.y = dot3( localNormal, localToGlobalY );
globalNormal.z = dot3( localNormal, localToGlobalZ );
globalNormal = normalize( globalNormal );
}
#endtemplate
/*
==================================================================================
CALC_FROM_VIEWER
==================================================================================
*/
#template CALC_FROM_VIEWER( fromViewerN, fromViewer )
{
fromViewerN = normalize( fromViewer.xyz );
}
#endtemplate
/*
==================================================================================
CALC_GLOBAL_REFLECTION
==================================================================================
*/
#template CALC_GLOBAL_REFLECTION( globalReflection, globalNormal, fromViewerN )
{
// reflection vector
globalReflection.xyz = fromViewerN - ( globalNormal * dot3( fromViewerN, globalNormal ) * 2.0 );
}
#endtemplate
/*
==================================================================================
SAMPLE_DIMSHADOW_BUFFER
==================================================================================
*/
#template SAMPLE_DIMSHADOW_BUFFER( shadow )
{
// this is normalized window space, not strict openGL window space
// that uses integer viewport values.
float3 window;
window.xy = screenPosToTexcoord( fragment.position.xy, $renderPositionToViewTexture );
// fetch the window space depth value
window.z = tex2Ddepth( $viewDepthMap, window.xy );
float4 wclip = float4( window.xyz, 1.0f );
// now transform to the light clip space
float4 light;
light.x = dot4( wclip, $windowPosToDimShadowBlurS );
light.y = dot4( wclip, $windowPosToDimShadowBlurT );
light.z = dot4( wclip, $windowPosToDimShadowBlurR );
light.w = dot4( wclip, $windowPosToDimShadowBlurQ );
// divide by w to get to light device coordinates
light.xyz /= light.w;
// move the -1.0 - 1.0 light device st to the 0.0 - 1.0 texture range
#ifdef XBOX
light.xy = ( light * 0.5 ) + 0.5; // don't adjust z, it is already 0 - 1
#else
light = ( light * 0.5 ) + 0.5;
#endif
#ifndef PC
light.y = 1.0 - light.y; // image y origin adjust
#endif
// clamp before sampling, because the shadow depth map may have
// only been updated in a restricted viewport
light.xy = min( light.xy, 0.99 );
light.xy = max( light.xy, 0.01 );
// make sure that the cleared z = 1.0 in the shadow buffer
// will always be farther away than any world surface
light.z = min( light.z, 0.9999999 );
// four samples
float2 tc = fragment.position.xy * float2( 1.0/128, 1.0/128 ) + $viewRandom.xy;
float2 dither = tex2D( $dither256map, tc ).xw;
const float step = 1.0 / 768.0; // FIXME: hard coded dim-shadow buffer size
float3 center;
// this biases by +1.5 on average, so we can test -3, -2, -1, 0 offsets
center.xy = light.xy + step + dither * step;
center.z = light.z;
shadow = shadow2Ddepth( $dimShadowDepthMap, center + float3( -2*step, -2*step, 0 ) );
shadow += shadow2Ddepth( $dimShadowDepthMap, center + float3( -1*step, -2*step, 0 ) );
shadow += shadow2Ddepth( $dimShadowDepthMap, center + float3( -2*step, -1*step, 0 ) );
shadow += shadow2Ddepth( $dimShadowDepthMap, center + float3( -1*step, -1*step, 0 ) );
shadow *= 0.25;
}
#endtemplate
/*
==================================================================================
APPLY_MODEL_FADE
==================================================================================
*/
#template APPLY_MODEL_FADE()
{
BRANCH if ( $modelFade.x < 1.0 ) {
float2 texcoord = fragment.position.xy * ( 1.0 / 256.0 );
float dither = tex2D( $dither256Map, texcoord ).x;
// 1 - fully opaque - 0.8 - stippling - 0.2 - fully transparent - 0
clip( $modelFade.x - 0.2 - dither * 0.6 );
}
}
#endtemplate
/*
==================================================================================
CALC_GRAZING
==================================================================================
*/
#template CALC_GRAZING( graze, globalNormal, fromViewerN )
{
/* calculate the view grazing fraction */
graze = saturate( dot3( -fromViewerN, globalNormal ) );
graze = saturate( ( $viewGraze.x - max( graze, -graze ) ) / max( $viewGraze.x, 0.0001 ) );
}
#endtemplate
/*
==================================================================================
APPLY_DIFFUSE_GRAZING
==================================================================================
*/
#template APPLY_DIFFUSE_GRAZING( diffuse, graze )
{
diffuse.xyz = lerp( diffuse.xyz, $grazingDiffuseColor.xyz, graze );
}
#endtemplate
/*
==================================================================================
APPLY_SPECULAR_GRAZING
==================================================================================
*/
#template APPLY_SPECULAR_GRAZING( specular, graze )
{
specular.xyz = lerp( specular.xyz, $grazingSpecularColor.xyz, graze );
}
#endtemplate
/*
==================================================================================
APPLY_GRAZING
==================================================================================
*/
#template APPLY_GRAZING( diffuse, specular, globalNormal, fromViewerN )
{
half graze;
CALC_GRAZING( graze, globalNormal, fromViewerN );
APPLY_DIFFUSE_GRAZING( diffuse, graze, );
APPLY_SPECULAR_GRAZING( specular, graze );
}
#endtemplate
/*
==================================================================================
APPLY_GRAZINGS
==================================================================================
*/
#template APPLY_GRAZINGS( diffuse, globalDiffuseNormal, specular, globalSpecularNormal, fromViewerN )
{
half grazeDiffuse;
half grazeSpecular;
CALC_GRAZING( grazeDiffuse, globalDiffuseNormal, fromViewerN );
CALC_GRAZING( grazeSpecular, globalSpecularNormal, fromViewerN );
APPLY_DIFFUSE_GRAZING( diffuse, grazeDiffuse );
APPLY_SPECULAR_GRAZING( specular, grazeSpecular );
}
#endtemplate
/*
==================================================================================
APPLY_RIMLIGHT
==================================================================================
*/
#template APPLY_RIMLIGHT( diffuse, globalNormal, fromViewer )
{
/* calculate the view grazing fraction */
half graze = 1.0 - saturate( dot3( -normalize( fromViewer ), globalNormal ) );
graze *= saturate( globalNormal.z );
graze = pow( graze, $RimlightColor.w );
diffuse.xyz += $rimlightColor.xyz * _half3( graze );
}
#endtemplate
/*
==================================================================================
APPLY_SCALING_SPECULAR
==================================================================================
*/
#template APPLY_SCALING_SPECULAR( specular )
{
specular.xyz *= $newSpecularScale.xyz;
}
#endtemplate
/*
==================================================================================
APPLY_SCALING_DIFFUSE
==================================================================================
*/
#template APPLY_SCALING_DIFFUSE( diffuse )
{
diffuse.xyz *= $newDiffuseScale.xyz * 2.0; /* why times two? */
}
#endtemplate
/*
==================================================================================
APPLY_SCALING
==================================================================================
*/
#template APPLY_SCALING( diffuse, specular )
{
APPLY_SCALING_DIFFUSE( diffuse )
APPLY_SCALING_SPECULAR( specular );
}
#endtemplate
/*
==================================================================================
APPLY_SPECULAR_REFLECTION
==================================================================================
*/
#template APPLY_SPECULAR_REFLECTION( specular, power, globalReflection )
{
/* Power factor is stored in sampleNormal.x as 0.0 - 1.0 */
/* We want a 0 | 1 | 2 | 3 mip value. */
/* The artists really prefer white to be shiny instead of dull, so invert it here. */
/* We could probably skip the floor, but I am wary of hardware / api rounding. */
globalReflection.w = floor( ( 1.0 - power ) * 4.0 + $newPowerScale.x );
half3 envColor = texCUBElod( $dynamicEnvMap, globalReflection ).xyz;
/* modulate by the environment mask map (specular channel) */
specular *= envColor;
}
#endtemplate
/*
==================================================================================
APPLY_FOLIAGE_SPECULAR
==================================================================================
*/
#template APPLY_FOLIAGE_SPECULAR( specular, power, globalNormal, fromViewer )
{
/* calculate the specular reflection vector from viewer and globalNormal */
half4 reflection;
reflection.xyz = fromViewer - ( globalNormal * dot3( fromViewer, globalNormal ) * 2.0 );
/* Power factor is stored in sampleNormal.x as 0.0 - 1.0 */
/* We want a 0 | 1 | 2 | 3 mip value. */
/* The artists really prefer white to be shiny instead of dull, so invert it here. */
/* We could probably skip the floor, but I am wary of hardware / api rounding. */
reflection.w = floor( ( 1.0 - power ) * 4.0 + $newPowerScale.x );
half3 envColor = texCUBElod( $dynamicEnvMap, reflection ).xyz;
/* modulate by the environment mask map (specular channel) */
envColor = lerp( _half3( max( max( envColor.x, envColor.y ), envColor.z ) ), envColor, _half3( $envSatScalePower.x ) );
envColor = pow( envColor, _half3( $envSatScalePower.z ) );
//envColor *= _half3( saturate( globalNormal.z + 1.0 ) );
specular *= envColor * _half3( $envSatScalePower.y );
}
#endtemplate
/*
==================================================================================
APPLY_PHYSICAL_SPECULAR
==================================================================================
*/
#template APPLY_PHYSICAL_SPECULAR( specular, surfaceSpecular, globalNormal, fromViewer )
{
/* calculate the specular reflection vector from viewer and globalNormal */
half4 reflection;
reflection.xyz = fromViewer - ( globalNormal * dot3( fromViewer, globalNormal ) * 2.0 );
//extract the color from the specular map
half3 specColor = normalize( surfaceSpecular.xyz ) * _half3( 1.73 );
//the gloss map is a greyscale version of the specular map
half glossMask = ( surfaceSpecular.x + surfaceSpecular.y + surfaceSpecular.z ) * 0.333;
//make dark parts of the spec map have less color
specColor = lerp( _half3( 1.0 ), specColor, glossMask );
glossMask = glossMask * $maxGloss.x;
half piMul = 0.039808917197; // 1 / ( pi * 8 )
half3 pSpecMask = _half3( ( glossMask + 8.0 ) * piMul );
half3 pSpecular = _half3( saturate( dot3( normalize( reflection.xyz ), $primeLightDir.xyz ) ) );
pSpecular *= pow( pSpecular, _half3( glossMask ) );
pSpecular *= $primeLightColor.xyz;
pSpecular *= pSpecMask * specColor;
specular += pSpecular;
}
#endtemplate
/*
==================================================================================
APPLY_MUZZLE_FLASH
==================================================================================
*/
#template APPLY_MUZZLE_FLASH( color, surfaceDiffuse, globalNormal, MFVector )
{
half muzzleFlash = saturate( dot( MFVector, globalNormal ) );
color.xyz += _half3( $gunMuzzleFlash.x * muzzleFlash * $gunMuzzleFlashColor.w ) * $gunMuzzleFlashColor.xyz * surfaceDiffuse;
}
#endtemplate
/*
==================================================================================
APPLY_LIGHTING_FOLIAGE
==================================================================================
*/
#template APPLY_LIGHTING_FOLIAGE( color, diffuse, specular, trueNormal, fromViewer, treeMask, transmissionMask )
{
//half treeMaskFromZ = saturate( ( 1.0 - treeMask ) * 5.0 );
//half3 trueNormal = lerp( globalNormal, treeNormal, 0.9 * treeMaskFromZ );
half ndotl = dot3( $primeLightDir, trueNormal );
half3 primeLightFactor = _half3( saturate( ndotl ) );
half3 primeLight = $primeLightColor.xyz * primeLightFactor;
half3 channelLight =
+ max( trueNormal.x * $channelLight0.xyz, 0 )
+ max( -trueNormal.x * $channelLight1.xyz, 0 )
+ max( trueNormal.y * $channelLight2.xyz, 0 )
+ max( -trueNormal.y * $channelLight3.xyz, 0 )
+ max( trueNormal.z * $channelLight4.xyz, 0 )
+ max( -trueNormal.z * $channelLight5.xyz, 0 );
half backLightFactor = pow( saturate( dot3( $primeLightDir, normalize( fromViewer ) ) ), 5.0 );
half backLightFalloff = pow( 1.0 - abs( ndotl ), 3.0 );
backLightFactor *= backLightFalloff * 3.0;
half3 backLight = $primeLightColor.xyz * transmissionMask.xyz * treeMask * backLightFactor;
half3 light = primeLight + channelLight + backLight;
/* maximum amount of dim-shadowing based on the pime light contribution */
float acceptDimShadow = max( primeLightFactor.x, max( primeLightFactor.y, primeLightFactor.z ) ) * ( 1.0 - saturate( 0.5 + $primeLightMin.x ) );
color.xyz = light * ( diffuse + specular );
color.w = acceptDimShadow;
}
#endtemplate
/*
==================================================================================
APPLY_LIGHTING
==================================================================================
*/
#template APPLY_LIGHTING( color, diffuse, specular, globalNormal )
{
half primeLightFactor = saturate( dot3( $primeLightDir, globalNormal ) );
half3 primeLight = $primeLightColor.xyz * primeLightFactor;
half3 channelLight =
+ max( globalNormal.x * $channelLight0.xyz, 0 )
+ max( -globalNormal.x * $channelLight1.xyz, 0 )
+ max( globalNormal.y * $channelLight2.xyz, 0 )
+ max( -globalNormal.y * $channelLight3.xyz, 0 )
+ max( globalNormal.z * $channelLight4.xyz, 0 )
+ max( -globalNormal.z * $channelLight5.xyz, 0 );
half3 light = primeLight + channelLight;
/* maximum amount of dim-shadowing based on the pime light contribution */
float acceptDimShadow = primeLightFactor * ( 1.0 - saturate( 0.5 + $primeLightMin.x ) );
color.xyz = light * ( diffuse + specular );
color.w = acceptDimShadow;
}
#endtemplate
/*
==================================================================================
APPLY_LIGHTING_NOAMBIENT
==================================================================================
*/
#template APPLY_LIGHTING_NOAMBIENT( color, diffuse, specular, globalNormal )
{
half primeLightFactor = saturate( dot3( $primeLightDir, globalNormal ) );
half3 primeLight = $primeLightColor.xyz * primeLightFactor;
half3 light = primeLight;
/* maximum amount of dim-shadowing based on the pime light contribution */
float acceptDimShadow = primeLightFactor * ( 1.0 - saturate( 0.5 + $primeLightMin.x ) );
color.xyz = light * ( diffuse + specular );
color.w = acceptDimShadow;
}
#endtemplate
/*
==================================================================================
APPLY_LIGHTING_ZHEIGHT
==================================================================================
*/
#template APPLY_LIGHTING_ZHEIGHT( color, diffuse, specular, globalNormal, height )
{
half primeLightFactor = saturate( dot3( $primeLightDir, globalNormal ) );
half3 primeLight = $primeLightColor.xyz * primeLightFactor;
half3 channelLight =
+ max( globalNormal.x * $channelLight0.xyz, 0 )
+ max( -globalNormal.x * $channelLight1.xyz, 0 )
+ max( globalNormal.y * $channelLight2.xyz, 0 )
+ max( -globalNormal.y * $channelLight3.xyz, 0 )
+ max( globalNormal.z * $channelLight4.xyz, 0 )
+ max( -globalNormal.z * $channelLight5.xyz, 0 );
half3 light = primeLight + channelLight;
/* modulate by the z-height blend */
light = lerp( channelLight, light, height );
/* maximum amount of dim-shadowing based on the pime light contribution */
float acceptDimShadow = primeLightFactor * ( 1.0 - saturate( 0.5 + $primeLightMin.x ) );
color.xyz = light * ( diffuse + specular );
color.w = acceptDimShadow;
}
#endtemplate
/*
==================================================================================
APPLY_LIGHTING_KEY
==================================================================================
*/
#template APPLY_LIGHTING_KEY( color, diffuse, specular, power, globalNormal, fromViewer,
primaryShadow, secondaryShadow, ambientScale, directScale )
{
half3 fromViewerN;
half3 globalReflection;
// reflection vector
CALC_FROM_VIEWER( fromViewerN, fromViewer );
CALC_GLOBAL_REFLECTION( globalReflection, globalNormal, fromViewerN );
half3 specularLight;
half3 diffuseLight;
//---------------------------------------------------------------
// primary light
//---------------------------------------------------------------
float primaryFactor = saturate( dot3( $primeLightDir, globalNormal ) );
float3 primeLight = primaryShadow * $primeLightColor.xyz * primaryFactor;
diffuseLight = primeLight;
// classic specular calculation
// power factor is stored in bumpPage.x as 0.0 - 1.0, with 1.0 being tightest highlights
float specDot = saturate( dot3( $primeLightDir, globalReflection ) );
specDot = pow( specDot, 1 + power * 40 );
specularLight = primeLight * specDot;
//---------------------------------------------------------------
// secondary light
//---------------------------------------------------------------
float secondaryFactor = saturate( dot3( $secondaryLightDir, globalNormal ) );
float3 secondaryLight = secondaryShadow * $secondaryLightColor.xyz * secondaryFactor;
diffuseLight += secondaryLight;
specDot = saturate( dot3( $secondaryLightDir, globalReflection ) );
specDot = pow( specDot, 1 + power * 40 );
specularLight += secondaryLight * specDot;
//---------------------------------------------------------------
// ambient lighting
//---------------------------------------------------------------
float3 ambientLight =
+ max( globalNormal.x * $channelLight0.xyz, 0 )
+ max( -globalNormal.x * $channelLight1.xyz, 0 )
+ max( globalNormal.y * $channelLight2.xyz, 0 )
+ max( -globalNormal.y * $channelLight3.xyz, 0 )
+ max( globalNormal.z * $channelLight4.xyz, 0 )
+ max( -globalNormal.z * $channelLight5.xyz, 0 );
//---------------------------------------------------------------
// height lerp
//---------------------------------------------------------------
// lerp in the diffuse lighting from the ground up
diffuseLight *= directScale;
specularLight *= directScale;
// lerp down the ambient from the ground up
diffuseLight += ambientLight * ambientScale;
//---------------------------------------------------------------
// sum everything up
//---------------------------------------------------------------
/* maximum amount of dim-shadowing based on the pime light contribution */
float acceptDimShadow = primaryFactor * ( 1.0 - saturate( 0.5 + $primeLightMin.x ) );
color.xyz = ( specularLight * specular.xyz ) + ( diffuseLight * diffuse.xyz );
color.w = acceptDimShadow;
}
#endtemplate
/*
==================================================================================
CALC_FRAGMENT_POS
==================================================================================
*/
#template CALC_FRAGMENT_POS( fragmentXYZ, fromViewer )
{
// world space coordinate of the fragment
// texcoord4 is fragmentXYZ - $globalViewOrigin.xyz;
fragmentXYZ = fromViewer + $globalViewOrigin.xyz;
}
#endtemplate
/*
==================================================================================
APPLY_LIGHTING
==================================================================================
*/
#template APPLY_LIGHTING_LOCAL( color, diffuse, specular, power, globalNormal, fragmentXYZ, globalReflection )
{
// power factor is stored in bumpPage.x as 0.0 - 1.0, with 1.0 being tightest highlights
const float powerExp = 4 + power * 100;
half3 specularLight = half3( 0, 0, 0 );
half3 diffuseLight = half3( 0, 0, 0 );
//---------------------------------------------------------------
// first light
//---------------------------------------------------------------
const float3 light0Dir = $channellight0.xyz - fragmentXYZ;
const float3 light0DirNormalized = normalize( light0Dir );
const float light0Dist = length( light0Dir );
const float light0Attenuation = 1.0 - ( min( light0Dist, $channellight1.w ) / $channellight1.w );
const float light0Factor = saturate( dot3( light0DirNormalized, globalNormal ) );
const float light0SpecDot = saturate( dot3( light0DirNormalized, globalReflection ) );
const float light0Pow = pow( light0SpecDot, powerExp );
const float3 light0Color = $channellight1.xyz * light0Factor * light0Attenuation;
diffuseLight += light0Color;
specularLight += light0Color * light0Pow;
//---------------------------------------------------------------
// second light
//---------------------------------------------------------------
const float3 light1Dir = $channellight2.xyz - fragmentXYZ;
const float3 light1DirNormalized = normalize( light1Dir );
const float light1Dist = length( light1Dir );
const float light1Attenuation = 1.0 - ( min( light1Dist, $channellight1.w ) / $channellight1.w );
const float light1Factor = saturate( dot3( light1DirNormalized, globalNormal ) );
const float light1SpecDot = saturate( dot3( light1DirNormalized, globalReflection ) );
const float light1Pow = pow( light1SpecDot, powerExp );
const float3 light1Color = $channellight3.xyz * light1Factor * light1Attenuation;
diffuseLight += light1Color;
specularLight += light1Color * light1Pow;
//---------------------------------------------------------------
// third light
//---------------------------------------------------------------
const float3 light2Dir = $channellight4.xyz - fragmentXYZ;
const float3 light2DirNormalized = normalize( light2Dir );
const float light2Dist = length( light2Dir );
const float light2Attenuation = 1.0 - ( min( light2Dist, $channellight1.w ) / $channellight1.w );
const float light2Factor = saturate( dot3( light2DirNormalized, globalNormal ) );
const float light2SpecDot = saturate( dot3( light2DirNormalized, globalReflection ) );
const float light2Pow = pow( light2SpecDot, powerExp );
const float3 light2Color = $channellight5.xyz * light2Factor * light2Attenuation;
diffuseLight += light2Color;
specularLight += light2Color * light2Pow;
//---------------------------------------------------------------
// sum everything up
//---------------------------------------------------------------
// the YCoCg conversion can go slightly negative!
diffuse = saturate( diffuse );
// de-gamma the textures
diffuse.x = pow( diffuse.x, 2.2 );
diffuse.y = pow( diffuse.y, 2.2 );
diffuse.z = pow( diffuse.z, 2.2 );
specular.x = pow( specular.x, 2.2 );
specular.y = pow( specular.y, 2.2 );
specular.z = pow( specular.z, 2.2 );
const float3 finalColor = ( specularLight * specular.xyz ) + ( diffuseLight * diffuse.xyz );
// gamma correct
color.x = pow( finalColor.x, 1.0/2.2 );
color.y = pow( finalColor.y, 1.0/2.2 );
color.z = pow( finalColor.z, 1.0/2.2 );
/* maximum amount of dim-shadowing based on the pime light contribution */
const half primeLightFactor = saturate( dot3( $primeLightDir, globalNormal ) )
* ( 1.0 - saturate( 0.5 + $primeLightMin.x ) ); // FIXME: make a constant!
color.w = primeLightFactor;
}
#endtemplate
/*
==================================================================================
APPLY_LIGHTING_SKIN
==================================================================================
*/
#template APPLY_LIGHTING_SKIN( color, diffuse, specular, ambientOcclusion, globalDiffuseNormal, globalReflection )
{
// Calculate diffuse warp from diffuse normal and use it as lookup
half cosd = saturate( ( dot3( $primeLightDir, globalDiffuseNormal ) * 0.5 ) + 0.5 );
half3 diffuseWarp = tex2D( $textureMap, float2( cosd, 0.0 ) ).xyz;
half specularAmbienceScale = 0.25;
half primeLightFactor = saturate( dot3( $primeLightDir, globalDiffuseNormal ) );
// Diffuse primary and ambient light
half3 diffusePrimary = $primeLightColor.xyz * diffuseWarp;
half3 diffuseAmbient = _half3( 0.0 )
+ max( globalDiffuseNormal.x * $channelLight0.xyz, 0.0 )
+ max( -globalDiffuseNormal.x * $channelLight1.xyz, 0.0 )
+ max( globalDiffuseNormal.y * $channelLight2.xyz, 0.0 )
+ max( -globalDiffuseNormal.y * $channelLight3.xyz, 0.0 )
+ max( globalDiffuseNormal.z * $channelLight4.xyz, 0.0 )
+ max( -globalDiffuseNormal.z * $channelLight5.xyz, 0.0 );
// Specular primary and ambient light
half3 specularPrimary = $primeLightColor.xyz * saturate( dot3( globalReflection, $primeLightDir ) );
half3 specularAmbient = _half3( 0.0 )
+ max( globalReflection.x * $channelLight0.xyz, 0.0 );
+ max( -globalReflection.x * $channelLight1.xyz, 0.0 );
+ max( globalReflection.y * $channelLight2.xyz, 0.0 );
+ max( -globalReflection.y * $channelLight3.xyz, 0.0 );
+ max( globalReflection.z * $channelLight4.xyz, 0.0 );
+ max( -globalReflection.z * $channelLight5.xyz, 0.0 );
// Apply ambient occlusion on ambient lights
diffuseAmbient *= ambientOcclusion;
specularAmbient *= ambientOcclusion * specularAmbienceScale;
half3 diffuseLight = diffusePrimary + diffuseAmbient;
half3 specularLight = specularPrimary + specularAmbient;
// Maximum amount of dim-shadowing based on the pime light contribution
float acceptDimShadow = primeLightFactor * ( 1.0 - saturate( 0.5 + $primeLightMin.x ) );
// Sum
color.xyz = _half3( 0.0 )
+ ( diffuseLight * diffuse )
+ ( specularLight * specular );
color.w = acceptDimShadow;
}
#endtemplate
/*
==================================================================================
APPLY_HOLOGRAM
==================================================================================
*/
#template APPLY_HOLOGRAM( color )
{
// scanline texture
float2 screenCoords = screenPosToTexcoord( fragment.position.xy, $positionToViewTexture );
half scanlinesWide = tex2D( $scanlineMap, screenCoords + ( $time.x * 0.025 ) ).x;
screenCoords *= float2( 1.0, 5.5 );
half scanlinesFine = tex2D( $scanlineMap, screenCoords + ( $time.x * 0.01 ) ).x;
color.xyz *= scanlinesWide + ( scanlinesFine * 0.25 ) ;
color.xyz *= 2.5;
color.xyz += $hologramColor.xyz * ( color.xyz + 0.1 );
color.xyz *= $hologramColor.w;
}
#endtemplate
/*
==================================================================================
APPLY_HIGHLIGHT
==================================================================================
*/
#template APPLY_HIGHLIGHT( color, fromViewerN, localToGlobalX, localToGlobalY, localToGlobalZ )
{
/* Reference,
This is the code we ran to get the approximated look of how we wanted the
rimming of usables to look like.
half k = 1.0 - saturate( abs( dot3( objectNormal.xyz, $globalViewFwd.xyz ) ) );
half bias = 0.25;
half scale = 1.0 / max( 1.0 - bias, 0.00001 );
half r = saturate( ( k - bias ) * scale );
color.xyz += _half3( r * r ) * half3( 0.968, 0.941, 0.705 ) * _half3( 1.0 );
*/
half3 objectNormal = half3( localToGlobalX.z, localToGlobalY.z, localToGlobalZ.z );
half k = 1.0 - saturate( abs( dot3( objectNormal.xyz, $globalViewFwd.xyz ) ) );
half r = ( k - 0.25 ) * 1.333333;
color.xyz += $highlightColor.xyz * _half3( r * r );
}
#endtemplate
/*
==================================================================================
OUTPUT_SURFACE_ATTRIBUTES
==================================================================================
*/
#template OUTPUT_SURFACE_ATTRIBUTES( diffuse, specular, power, globalNormal )
{
#ifdef DEFERRED_LIGHTING
result.color2.xyz = diffuse.xyz;
result.color2.w = length( specular.xyz );
result.color3.xyz = globalNormal.xyz * _float3( 0.5 ) + _float3( 0.5 );
result.color3.w = power;
#endif
}
#endtemplate
@@ -0,0 +1,32 @@
#template SAMPLE_WRINKLEMAPS( occlusionRes, bumpRes, occlusionSrc, bumpSrc, texCoord )
{
half4 mask01 = tex2D( $fadeMap, float2( texCoord.x * 0.5f, texCoord.y ) );
half4 mask23 = tex2D( $fadeMap, float2( texCoord.x * 0.5f + 0.5f, texCoord.y ) );
mask01 = (mask01 - 0.50f)*2.2f;
float wrinkleResFactor0 = (dot4(saturate(mask01 - 0.05f), $wrinkleFactor0)
+ dot4(saturate(-mask01 - 0.05f), $wrinkleFactor1) );
mask23 = (mask23 - 0.50f)*2.2f;
float wrinkleResFactor1 = (dot4(saturate(mask23 - 0.05f), $wrinkleFactor2)
+ dot4(saturate(-mask23 - 0.05f), $wrinkleFactor3) );
float wrinkleResFactor = clamp( wrinkleResFactor0 + wrinkleResFactor1, -1.0f, 1.0f );
wrinkleResFactor *= $wrinkleScale.x;
float ambOccl = occlusionSrc.g;
half4 bumpNormal = bumpSrc;
// + is expand, - is contract
if ( wrinkleResFactor > 0.05 ) {
ambOccl = lerp( occlusionSrc.g, occlusionSrc.b, wrinkleResFactor );
bumpNormal = lerp( bumpSrc, tex2D( $spareBumpMap2, texCoord.xy ), wrinkleResFactor );
} else if ( wrinkleResFactor < -0.05 ) {
ambOccl = lerp( occlusionSrc.g, occlusionSrc.r, -wrinkleResFactor );
bumpNormal = lerp( bumpSrc, tex2D( $spareBumpMap1, texCoord.xy ), -wrinkleResFactor );
}
occlusionRes = ambOccl;
bumpRes = bumpNormal;
}
#endtemplate
@@ -0,0 +1,52 @@
// Store fog and frame fraction value
float fogVal = fragment.texcoord0.z;
float frameFrac = fragment.texcoord1.z;
#ifdef PARTICLE_FP_ALT
// Remove trans-atlas coordinate mapping if we're using atlas coords
half2 texcoord0 = ( fragment.texcoord0.xy - $transAtlasScaleBiasInv.zw ) * $transAtlasScaleBiasInv.xy;
half2 texcoord1 = ( fragment.texcoord1.xy - $transAtlasScaleBiasInv.zw ) * $transAtlasScaleBiasInv.xy;
#else
// Simple copy texture coordinates from vertex program output
half2 texcoord0 = fragment.texcoord0.xy;
half2 texcoord1 = fragment.texcoord1.xy;
#endif
// Sample extra parameters if needed
#if defined( PARTICLE_FP_MASK_LUT ) || defined( PARTICLE_FP_MOD_TEXCOORD )
half2 texcoord2;
texcoord2.x = dot4( fragment.texcoord2.xy, $sMatrix );
texcoord2.y = dot4( fragment.texcoord2.xy, $tMatrix );
half4 parm = tex2D( $textureMap, texcoord2 );
#endif
// Offset texture coordinates
#ifdef PARTICLE_FP_MOD_TEXCOORD
half2 offset = parm.xy * _half2( 2.0 ) - _half2( 1.0 );
offset *= _half2( $distortionScale.x );
texcoord0 += offset;
texcoord1 += offset;
#endif
// Sample color from either transMap1 or transMap depending on wheter we're running alternative particle program or not
#ifdef PARTICLE_FP_ALT
half4 color = ComputeAnimCrossFadeColor( $transMap1, texcoord0, texcoord1, frameFrac );
#else
half4 color = ComputeAnimCrossFadeColor( $transMap, texcoord0, texcoord1, frameFrac );
#endif
#ifdef PARTICLE_FP_MASK_LUT
half3 coordLUT = max( min( color.xyz * _half3( parm.z ), _half3( 1.0 - 0.015625 ) ), _half3( 0.015625 ) );
color.x = tex2D( $transMap2, half2( coordLUT.x, 0.5 ) ).x;
color.y = tex2D( $transMap2, half2( coordLUT.y, 0.5 ) ).y;
color.z = tex2D( $transMap2, half2( coordLUT.z, 0.5 ) ).z;
#endif
@@ -0,0 +1,35 @@
result.position.x = dot4( vertex.position, $mvpMatrixX );
result.position.y = dot4( vertex.position, $mvpMatrixY );
result.position.z = dot4( vertex.position, $mvpMatrixZ );
result.position.w = dot4( vertex.position, $mvpMatrixW );
const float eyeDist = result.position.w;
const float frameFrac = vertex.tangent.z;
const float alphascale = vertex.tangent.w;
// fade particle based on distance to near clip
float fade = saturate( abs( eyeDist ) * $particleFade.x );
const float fogTerm = -( clamp( eyeDist - $fogStart.x, 0.0, $fogEnd.x ) * $fogScale.x );
// moving the fogVal calculation to the vert shader for particles does not appear to cause any artifacts
const float fogVal = saturate( exp2( fogTerm ) );
// Convert back from 16 bit vertex elements.
result.texcoord0.xy = vertex.texcoord0.xy * $particleStScaleBias.x + $particleStScaleBias.y;
result.texcoord0.z = fogVal;
result.texcoord0.w = 0.0;
#ifndef VP_SINGLETEXCOORD
// Convert back from 16 bit vertex elements.
result.texcoord1.xy = vertex.texcoord1.xy * $particleStScaleBias.x + $particleStScaleBias.y;
result.texcoord1.z = frameFrac;
result.texcoord1.w = 0.0;
#endif
#ifdef VP_UNITTEXCOORD
result.texcoord2.xy = vertex.tangent.xy;
result.texcoord2.zw = vertex.tangent.xy;
#endif
float4 vertColor = swizzleColor( vertex.color );
+284
View File
@@ -0,0 +1,284 @@
// Convert back from 16 bit vertex elements.
float4 position = vertex.position * $vertexXYZScale + $vertexXYZBias;
#if defined( XBOX )
if ( bHardwareSkinning ) {
float4 vertexPosition = position;
if ( bHardwareMorphing ) {
#if 0
// Fetch the morph value with inline asm,
// so it only gets getched when bHardwareMorphing is
// enabled. If we just used vertex.morph.xyz, it would
// always be fetched, and gives streams of Pix warnings
// when the stream buffer is bound to NULL.
float4 vertexMorph;
int index = vertex.index;
asm {
vfetch vertexMorph, index, color2
};
float3 morphVector = ( vertexMorph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertexMorph.w * 32.0f );
#else
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
#endif
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.a * 255.1;
asm {
vfetch matX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch matY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch matZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX *= w0;
matY *= w0;
matZ *= w0;
float4 tmatX, tmatY, tmatZ;
joint = vertex.color.b * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w1;
matY += tmatY * w1;
matZ += tmatZ * w1;
joint = vertex.color.g * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w2;
matY += tmatY * w2;
matZ += tmatZ * w2;
joint = vertex.color.r * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w3;
matY += tmatY * w3;
matZ += tmatZ * w3;
position.x = dot4( vertexPosition, matX );
position.y = dot4( vertexPosition, matY );
position.z = dot4( vertexPosition, matZ );
position.w = 1.0;
}
#elif defined( PS3 )
if ( hardwareSkinning ) {
float4 vertexPosition = position;
if ( hardwareMorphing ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255.1 * 3;
matX = matrices[joint+0] * w0;
matY = matrices[joint+1] * w0;
matZ = matrices[joint+2] * w0;
joint = vertex.color.g * 255.1 * 3;
matX += matrices[joint+0] * w1;
matY += matrices[joint+1] * w1;
matZ += matrices[joint+2] * w1;
joint = vertex.color.b * 255.1 * 3;
matX += matrices[joint+0] * w2;
matY += matrices[joint+1] * w2;
matZ += matrices[joint+2] * w2;
joint = vertex.color.a * 255.1 * 3;
matX += matrices[joint+0] * w3;
matY += matrices[joint+1] * w3;
matZ += matrices[joint+2] * w3;
position.x = dot4( vertexPosition, matX );
position.y = dot4( vertexPosition, matY );
position.z = dot4( vertexPosition, matZ );
position.w = 1.0;
}
#elif defined( PC_D3D )
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = position;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
position.x = dot4( vertexPosition, matX );
position.y = dot4( vertexPosition, matY );
position.z = dot4( vertexPosition, matZ );
position.w = 1.0;
}
#elif defined( PC )
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = position;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
vertexPosition.xyz += ( morphVector * vertex.morph.w * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
if ( hardwareSkinning.z == 0.0 ) {
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
position.x = dot4( vertexPosition, matX );
position.y = dot4( vertexPosition, matY );
position.z = dot4( vertexPosition, matZ );
position.w = 1.0;
} else {
float4 dualQuats[ 8 ];
float joint = vertex.color.r * 255;
dualQuats[0] = matrices[ int(joint*2+0) ];
dualQuats[1] = matrices[ int(joint*2+1) ];
joint = vertex.color.g * 255;
dualQuats[2] = matrices[ int(joint*2+0) ];
dualQuats[3] = matrices[ int(joint*2+1) ];
joint = vertex.color.b * 255;
dualQuats[4] = matrices[ int(joint*2+0) ];
dualQuats[5] = matrices[ int(joint*2+1) ];
joint = vertex.color.a * 255;
dualQuats[6] = matrices[ int(joint*2+0) ];
dualQuats[7] = matrices[ int(joint*2+1) ];
// Find rot directions
if (dot4(dualQuats[0], dualQuats[2]) < 0.0)
w1 = -w1;
if (dot4(dualQuats[0], dualQuats[4]) < 0.0)
w2 = -w2;
if (dot4(dualQuats[0], dualQuats[6]) < 0.0)
w3 = -w3;
// blend dualquats
float4 Trans0 = dualQuats[0] * w0;
float4 Trans1 = dualQuats[1] * w0;
Trans0 += dualQuats[2] * w1;
Trans1 += dualQuats[3] * w1;
Trans0 += dualQuats[4] * w2;
Trans1 += dualQuats[5] * w2;
Trans0 += dualQuats[6] * w3;
Trans1 += dualQuats[7] * w3;
// Normalize
float invlen = 1.0/length(Trans0);
Trans0 *= invlen;
Trans1 *= invlen;
float4 LocPos = vertexPosition;
position.xyz = LocPos.xyz + 2.0 * cross(Trans0.xyz, cross(Trans0.xyz, LocPos.xyz) + Trans0.w * LocPos.xyz);
position.xyz += 2.0 * (Trans0.w * Trans1.xyz - Trans1.w * Trans0.xyz + cross(Trans0.xyz, Trans1.xyz));
position.w = 1.0;
}
}
#else
#error "unknown platform"
#endif
@@ -0,0 +1,339 @@
// Convert back from 16 bit vertex elements.
float4 position = vertex.position * $vertexXYZScale + $vertexXYZBias;
float4 normal = vertex.normal * 2.0 - 1.0;
float4 tangent = vertex.tangent * 2.0 - 1.0;
float morphScale = 0.0f;
#if defined( XBOX )
if ( bHardwareSkinning ) {
float4 vertexPosition = position;
if ( bHardwareMorphing ) {
#if 0
// Fetch the morph value with inline asm,
// so it only gets getched when bHardwareMorphing is
// enabled. If we just used vertex.morph.xyz, it would
// always be fetched, and gives streams of Pix warnings
// when the stream buffer is bound to NULL.
float4 vertexMorph;
int index = vertex.index;
asm {
vfetch vertexMorph, index, color2
};
float3 morphVector = ( vertexMorph.xyz * 2 ) - 1;
morphScale = vertexMorph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
#else
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
#endif
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.a * 255.1;
asm {
vfetch matX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch matY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch matZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX *= w0;
matY *= w0;
matZ *= w0;
float4 tmatX, tmatY, tmatZ;
joint = vertex.color.b * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w1;
matY += tmatY * w1;
matZ += tmatZ * w1;
joint = vertex.color.g * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w2;
matY += tmatY * w2;
matZ += tmatZ * w2;
joint = vertex.color.r * 255.1;
asm {
vfetch tmatX, joint, position1, UseTextureCache=true, RoundIndex = true
vfetch tmatY, joint, position2, UseTextureCache=true, RoundIndex = true
vfetch tmatZ, joint, position3, UseTextureCache=true, RoundIndex = true
};
matX += tmatX * w3;
matY += tmatY * w3;
matZ += tmatZ * w3;
position.x = dot4( vertexPosition, matX );
position.y = dot4( vertexPosition, matY );
position.z = dot4( vertexPosition, matZ );
position.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
}
#elif defined( PS3 )
if ( hardwareSkinning ) {
float4 vertexPosition = position;
if ( hardwareMorphing ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
}
// multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )
float weights = vertex.normal.w * 255.1; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255.1 * 3;
matX = matrices[joint+0] * w0;
matY = matrices[joint+1] * w0;
matZ = matrices[joint+2] * w0;
joint = vertex.color.g * 255.1 * 3;
matX += matrices[joint+0] * w1;
matY += matrices[joint+1] * w1;
matZ += matrices[joint+2] * w1;
joint = vertex.color.b * 255.1 * 3;
matX += matrices[joint+0] * w2;
matY += matrices[joint+1] * w2;
matZ += matrices[joint+2] * w2;
joint = vertex.color.a * 255.1 * 3;
matX += matrices[joint+0] * w3;
matY += matrices[joint+1] * w3;
matZ += matrices[joint+2] * w3;
position.x = dot4( vertexPosition, matX );
position.y = dot4( vertexPosition, matY );
position.z = dot4( vertexPosition, matZ );
position.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
}
#elif defined( PC_D3D )
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = position;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
position.x = dot4( vertexPosition, matX );
position.y = dot4( vertexPosition, matY );
position.z = dot4( vertexPosition, matZ );
position.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
}
#elif defined( PC )
if ( hardwareSkinning.x != 0.0 ) {
float4 vertexPosition = position;
if ( hardwareSkinning.y != 0.0 ) {
float3 morphVector = ( vertex.morph.xyz * 2 ) - 1;
morphScale = vertex.morph.w;
vertexPosition.xyz += ( morphVector * morphScale * 32.0f );
}
float weights = vertex.normal.w * 255; // [0, 1] -> [0, 255]
float w1 = floor( weights / 16 ); // [0, 15] (= 4 bits)
float w2 = floor( weights / 4 ) - ( w1 * 4 ); // [0, 3] (= 2 bits)
float w3 = weights - ( w2 * 4 ) - ( w1 * 16 ); // [0, 3] (= 2 bits)
w1 *= 1.0 / 30.0; // [0, 15] -> [0, 1/2]
w2 *= 1.0 / 9.0; // [0, 3] -> [0, 1/3]
w3 *= 1.0 / 12.0; // [0, 3] -> [0, 1/4]
float w0 = 1 - ( w1 + w2 + w3 ); // [1/4, 1]
if ( hardwareSkinning.z == 0.0 ) {
float4 matX, matY, matZ;
float joint = vertex.color.r * 255;
matX = matrices[int(joint*3+0)] * w0;
matY = matrices[int(joint*3+1)] * w0;
matZ = matrices[int(joint*3+2)] * w0;
joint = vertex.color.g * 255;
matX += matrices[int(joint*3+0)] * w1;
matY += matrices[int(joint*3+1)] * w1;
matZ += matrices[int(joint*3+2)] * w1;
joint = vertex.color.b * 255;
matX += matrices[int(joint*3+0)] * w2;
matY += matrices[int(joint*3+1)] * w2;
matZ += matrices[int(joint*3+2)] * w2;
joint = vertex.color.a * 255;
matX += matrices[int(joint*3+0)] * w3;
matY += matrices[int(joint*3+1)] * w3;
matZ += matrices[int(joint*3+2)] * w3;
position.x = dot4( vertexPosition, matX );
position.y = dot4( vertexPosition, matY );
position.z = dot4( vertexPosition, matZ );
position.w = 1.0;
float4 tempNormal = normal;
normal.x = dot3( tempNormal, matX );
normal.y = dot3( tempNormal, matY );
normal.z = dot3( tempNormal, matZ );
float4 tempTangent = tangent;
tangent.x = dot3( tempTangent, matX );
tangent.y = dot3( tempTangent, matY );
tangent.z = dot3( tempTangent, matZ );
} else {
// Dual quat skinning
float4 dualQuats[ 8 ];
float joint = vertex.color.r * 255;
dualQuats[0] = matrices[ int(joint*2+0) ];
dualQuats[1] = matrices[ int(joint*2+1) ];
joint = vertex.color.g * 255;
dualQuats[2] = matrices[ int(joint*2+0) ];
dualQuats[3] = matrices[ int(joint*2+1) ];
joint = vertex.color.b * 255;
dualQuats[4] = matrices[ int(joint*2+0) ];
dualQuats[5] = matrices[ int(joint*2+1) ];
joint = vertex.color.a * 255;
dualQuats[6] = matrices[ int(joint*2+0) ];
dualQuats[7] = matrices[ int(joint*2+1) ];
// Find rot directions
if (dot4(dualQuats[0], dualQuats[2]) < 0.0)
w1 = -w1;
if (dot4(dualQuats[0], dualQuats[4]) < 0.0)
w2 = -w2;
if (dot4(dualQuats[0], dualQuats[6]) < 0.0)
w3 = -w3;
// blend dualquats
float4 Trans0 = dualQuats[0] * w0;
float4 Trans1 = dualQuats[1] * w0;
Trans0 += dualQuats[2] * w1;
Trans1 += dualQuats[3] * w1;
Trans0 += dualQuats[4] * w2;
Trans1 += dualQuats[5] * w2;
Trans0 += dualQuats[6] * w3;
Trans1 += dualQuats[7] * w3;
// Normalize
float invlen = 1.0/length(Trans0);
Trans0 *= invlen;
Trans1 *= invlen;
float4 LocPos = vertexPosition;
position.xyz = LocPos.xyz + 2.0 * cross(Trans0.xyz, cross(Trans0.xyz, LocPos.xyz) + Trans0.w * LocPos.xyz);
position.xyz += 2.0 * (Trans0.w * Trans1.xyz - Trans1.w * Trans0.xyz + cross(Trans0.xyz, Trans1.xyz));
position.w = 1.0;
normal.xyz = normal.xyz + 2.0 * cross(Trans0.xyz, cross(Trans0.xyz, normal.xyz) + Trans0.w * normal.xyz);
tangent.xyz = tangent.xyz + 2.0 * cross(Trans0.xyz, cross(Trans0.xyz, tangent.xyz) + Trans0.w * tangent.xyz);
}
}
#else
#error "unknown platform"
#endif
float3 bitangent = cross( normal.xyz, tangent.xyz ) * tangent.w;
@@ -0,0 +1,15 @@
#ifdef XBOX
float interpolatedZOverW = fragment.texcoord3.z / fragment.texcoord3.w;
#else
float interpolatedZOverW = fragment.position.z;
#endif
float fogVal = fragment.texcoord0.z;
float alphaScale = fragment.texcoord0.w;
float frameFrac = fragment.texcoord1.z;
float2 screenTC = screenPosToTexcoord( fragment.position.xy, $renderPositionToViewTexture );
float scale = ComputeSoftParticleScale( $viewDepthMap, screenTC, interpolatedZOverW, alphaScale );
half4 color = ComputeAnimCrossFadeColor( $transMap, fragment.texcoord0.xy, fragment.texcoord1.xy, frameFrac );
@@ -0,0 +1,48 @@
result.position.x = dot4( vertex.position, $mvpMatrixX );
result.position.y = dot4( vertex.position, $mvpMatrixY );
result.position.z = dot4( vertex.position, $mvpMatrixZ );
result.position.w = dot4( vertex.position, $mvpMatrixW );
const float eyeDist = result.position.w;
const float frameFrac = vertex.tangent.z;
const float alphascale = vertex.tangent.w;
const float4 genericParm = vertex.normal;
// create thickness based on alpha scale
float thickness = ( ( 1.0 - alphascale ) * 127.0 ) / eyeDist;
// fade particle based on distance to near clip and thickness
float fade = saturate( abs( eyeDist ) / ( ( 1.0 - alphascale ) * 127.0 ) );
const float fogTerm = -( clamp( eyeDist - $fogStart.x, 0.0, $fogEnd.x ) * $fogScale.x );
// moving the fogVal calculation to the vert shader for particles does not appear to cause any artifacts
const float fogVal = saturate( exp2( fogTerm ) );
// Convert back from 16 bit vertex elements.
result.texcoord0.xy = vertex.texcoord0.xy * $particleStScaleBias.x + $particleStScaleBias.y;
result.texcoord0.z = fogVal;
result.texcoord0.w = alphascale;
// Convert back from 16 bit vertex elements.
result.texcoord1.xy = vertex.texcoord1.xy * $particleStScaleBias.x + $particleStScaleBias.y;
result.texcoord1.z = frameFrac;
result.texcoord1.w = 0.0;
//result.texcoord2.x = genericParm.x * 10.0 + 1.0; // color multiply
//result.texcoord2.y = genericParm.y * 10.0 + 1.0; // alpha multiply
//result.texcoord2.z = 1.0 - genericParm.z; // color screen
//result.texcoord2.w = genericParm.w; //
// pw-note: this works absolutely crap if you have particles locked in certain axes.
// light streaks will have a fake depth that isn't really correct and end up infront of depth causing flickering
// Use the 'Depth Offset' in the particle system instead to achive exactly this in a proper way.
// adding half of the alpha scale to create a fake thickness to the particle
// makes particles that are flat against surfaces show up much better, result: need fewer particles.
//result.position.z -= thickness;
#ifdef XBOX
result.texcoord3 = result.position;
#endif
float4 vertColor = swizzleColor( vertex.color );
@@ -0,0 +1 @@
{ Tex _screenMip3_alt }
@@ -0,0 +1 @@
{ Vec 1 }
@@ -0,0 +1 @@
{ Vec { 1.0, 1.0, 1.0, 1.0 } }
@@ -0,0 +1 @@
{ Tex _screenMip3_alt }
@@ -0,0 +1 @@
{ Tex _screenMip3 }
@@ -0,0 +1 @@
{ Vec { 0.2, 0.8, 0.5, 0.1 } }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Tex _luminosityImage }
@@ -0,0 +1 @@
{ Program 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 1 bool }
@@ -0,0 +1 @@
{ Vec 64 range 1.0, 100.0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ String "" }
@@ -0,0 +1 @@
{ Vec 64 }
@@ -0,0 +1 @@
{ Environment env/ambiTest_px }
@@ -0,0 +1 @@
{ Vec 1 }
@@ -0,0 +1 @@
{ Program 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Tex _default }
@@ -0,0 +1 @@
{ Tex _default }
@@ -0,0 +1 @@
{ Tex _default }
@@ -0,0 +1 @@
{ Program 0 }
@@ -0,0 +1 @@
{ Vec 1.0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ String constantColor(0.5,0.5,1,0) }
@@ -0,0 +1 @@
{ Vec 0 range -1.0, 1.0 }
@@ -0,0 +1 @@
{ Vec 1 range 0.4, 1.8 }
@@ -0,0 +1 @@
{ Vec 1 range 0.0, 1.0 }
@@ -0,0 +1 @@
{ Vec 0 range 0.0, 1.0 }
@@ -0,0 +1 @@
{ Vec 1 range 0.0, 1.0 }
@@ -0,0 +1 @@
{ Vec 0 range 0.0, 1.0 }
@@ -0,0 +1 @@
{ Tex _colorBalanceLUT }
@@ -0,0 +1 @@
{ Vec { 0.0 } range 0.0, 1.0 }
@@ -0,0 +1 @@
{ Vec { 0, 0, 0, 1 } range -100.0, 100.0 }
@@ -0,0 +1 @@
{ Vec { 0, 0, 0, 1 } range -100.0, 100.0 }
@@ -0,0 +1 @@
{ Vec { 0, 0, 0, 1 } range -100.0, 100.0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 1 }
@@ -0,0 +1 @@
{ Vec 1 }
@@ -0,0 +1 @@
{ Vec { 1, 1, 1, 1 } color }
@@ -0,0 +1 @@
{ Vec 1 }
@@ -0,0 +1 @@
{ Vec 268435456 }
@@ -0,0 +1 @@
{ Vec 33554432 }
@@ -0,0 +1 @@
{ Vec 134217728 }
@@ -0,0 +1 @@
{ Vec 67108864 }
@@ -0,0 +1 @@
{ Vec 536870912 }
@@ -0,0 +1 @@
{ Vec 1024 }
@@ -0,0 +1 @@
{ Vec 512 }
@@ -0,0 +1 @@
{ Vec 8192 }
@@ -0,0 +1 @@
{ Vec 262144 }
@@ -0,0 +1 @@
{ Vec 4096 }
@@ -0,0 +1 @@
{ Vec 256 }
@@ -0,0 +1 @@
{ Vec 16 }
@@ -0,0 +1 @@
{ Vec 1048576 }
@@ -0,0 +1 @@
{ Vec 64 }
@@ -0,0 +1 @@
{ Vec 1073741824 }
@@ -0,0 +1 @@
{ Vec 0 }
@@ -0,0 +1 @@
{ Vec 131072 }
@@ -0,0 +1 @@
{ Vec 2 }
@@ -0,0 +1 @@
{ Vec 32768 }
@@ -0,0 +1 @@
{ Vec 8 }
@@ -0,0 +1 @@
{ Vec 524288 }
@@ -0,0 +1 @@
{ Vec 2097152 }
@@ -0,0 +1 @@
{ Vec 2048 }
@@ -0,0 +1 @@
{ Vec 128 }
@@ -0,0 +1 @@
{ Vec 1 }
@@ -0,0 +1 @@
{ Vec 16777216 }
@@ -0,0 +1 @@
{ Vec 16384 }
@@ -0,0 +1 @@
{ Vec 4 }
@@ -0,0 +1 @@
{ Vec 1 }
@@ -0,0 +1 @@
{ String constantColor(1,1,1,1) }

Some files were not shown because too many files have changed in this diff Show More