Interesting... Went home as I have an AMD Vega 64 there and I still get the same issue.
There is an obvious compile error 'variable not completely initialised' type error, see below
Code: Select all
#if 0
*** [Hash 0x010d84dd] 2
*** [Hash 0x06285893] 0
*** [Hash 0x0790ba12] 4
*** [Hash 0x086bb3a6] 0
*** [Hash 0x0ac4ff20] 3
*** [Hash 0x0b4678e4] 1
*** [Hash 0x0c7e761b] 4
*** [Hash 0x1185e86f] 0
*** [Hash 0x123606a9] 0
*** [Hash 0x15cb74a1] 0
*** [Hash 0x16e62810] 3
*** [Hash 0x1825f286] 3
*** [Hash 0x19a61682] 1
*** [Hash 0x1af900a2] 1
*** [Hash 0x1b0c2b69] 0
*** [Hash 0x1bab8cdd] 0
*** [Hash 0x1bb5acac] 0
*** [Hash 0x1e8b5671] 50000
*** [Hash 0x1f2c6e82] 0
*** [Hash 0x21515f80] 3
*** [Hash 0x2337351f] 8
*** [Hash 0x24d6fb8f] 1
*** [Hash 0x25dc73c6] 635204550
*** [Hash 0x26249384] 42857
*** [Hash 0x2a892b58] 0
*** [Hash 0x2cb6ab02] 0
*** [Hash 0x2dd3a2cd] 0
*** [Hash 0x354d66c0] 3
*** [Hash 0x359e8062] 1
*** [Hash 0x360c3db1] 0
*** [Hash 0x38942648] 3
*** [Hash 0x39384d5a] 28571
*** [Hash 0x3b038020] 0
*** [Hash 0x3d790219] 3
*** [Hash 0x3dde9817] 1
*** [Hash 0x3f315fff] 0
*** [Hash 0x3fcb60f1] 1070293233
*** [Hash 0x415a738b] 0
*** [Hash 0x4508a85c] 1
*** [Hash 0x45d6475f] 0
*** [Hash 0x4614eb82] 3
*** [Hash 0x46bba485] 0
*** [Hash 0x491233c3] 0
*** [Hash 0x4956ca9a] 1
*** [Hash 0x4ec19020] 1
*** [Hash 0x4feb7b6e] 1
*** [Hash 0x51de8f13] 42857
*** [Hash 0x549bb006] 0
*** [Hash 0x55683ca9] 1
*** [Hash 0x57643473] 3
*** [Hash 0x5a23f9f0] 0
*** [Hash 0x5ca459ef] 0
*** [Hash 0x5cb4719a] 1
*** [Hash 0x5dbe1dca] 1
*** [Hash 0x62055e42] 3
*** [Hash 0x66ac9d57] 0
*** [Hash 0x675280f4] 0
*** [Hash 0x6962e498] 1
*** [Hash 0x6be92c72] 0
*** [Hash 0x6caa2971] 2
*** [Hash 0x6d28c426] 2
*** [Hash 0x6f177a79] 0
*** [Hash 0x717564b5] 0
*** [Hash 0x71dd9ea9] 4
*** [Hash 0x74824502] 1
*** [Hash 0x74a9afe4] 1
*** [Hash 0x76277703] 3
*** [Hash 0x7633d79c] 3
*** [Hash 0x790cdbbe] 0
*** [Hash 0x7a148ebc] 0
*** [Hash 0x7ae862a6] 0
*** [Hash 0x7e8dec1c] 0
*** [Hash 0x7e934f0e] 0
*** [Hash 0x8040ea88] 28571
*** [Hash 0x8045c1b4] 1
*** [Hash 0x840f5b80] 0
*** [Hash 0x8421366d] 2
*** [Hash 0x86319b9f] 1
*** [Hash 0x875516cf] 0
*** [Hash 0x8857c26f] 0
*** [Hash 0x899520b9] 2
*** [Hash 0x91f755f3] 0
*** [Hash 0x92baf270] 0
*** [Hash 0x9313c759] 0
*** [Hash 0x93f2327b] -334286542
*** [Hash 0x94b1117a] -1
*** [Hash 0x962aeb1a] 1
*** [Hash 0x969b85a2] 3
*** [Hash 0x96c12323] 1
*** [Hash 0x9abd84b5] -1698855755
*** [Hash 0xa0b3d929] 3
*** [Hash 0xa461daa9] 1
*** [Hash 0xa62cee23] 0
*** [Hash 0xa69f72d5] 2
*** [Hash 0xa6ac776b] 0
*** [Hash 0xa89ac41a] 1
*** [Hash 0xa90324bb] 0
*** [Hash 0xa9ef564e] 3
*** [Hash 0xab18cda0] 1
*** [Hash 0xb22f037a] 0
*** [Hash 0xb7b857ae] 1
*** [Hash 0xb9201184] 0
*** [Hash 0xb967bb7b] 0
*** [Hash 0xbb17ed32] 3
*** [Hash 0xbc128c23] 0
*** [Hash 0xc0a55ecd] 3
*** [Hash 0xc16170c0] 0
*** [Hash 0xc163417f] 3
*** [Hash 0xc19750c1] 3
*** [Hash 0xc377e795] 50000
*** [Hash 0xc46d5eba] 1
*** [Hash 0xc5a41055] 3
*** [Hash 0xc5ed03e2] 1
*** [Hash 0xc7cccc57] 0
*** [Hash 0xcb33bcfe] 0
*** [Hash 0xcef10401] 1
*** [Hash 0xd17f1d1c] 1
*** [Hash 0xd62dae30] 4
*** [Hash 0xd7ec9987] 1
*** [Hash 0xdc23368e] 0
*** [Hash 0xde8359cf] 1
*** [Hash 0xdf16de3a] 1
*** [Hash 0xe40b2520] 1
*** [Hash 0xe7bd0fde] 0
*** [Hash 0xe91dc048] 2
*** [Hash 0xe9b3b96d] 0
*** [Hash 0xebb7ea44] 1
*** [Hash 0xebfcdcac] 28571
*** [Hash 0xec133132] -334286542
*** [Hash 0xec4e19ce] 0
*** [Hash 0xf6eb512d] 0
DONE DUMPING PROPERTIES
*** [Hash 0xcbb75443] @insertpiece( NormalNonPremul)
DONE DUMPING PIECES
#endif
//#include "SyntaxHighlightingMisc.h"
#define ushort uint
#define ogre_float4x3 float4x3
//Short used for read operations. It's an int in GLSL & HLSL. An ushort in Metal
#define rshort2 int2
//Short used for write operations. It's an int in GLSL. An ushort in HLSL & Metal
#define wshort2 uint2
#define toFloat3x3( x ) ((float3x3)(x))
#define buildFloat3x3( row0, row1, row2 ) transpose( float3x3( row0, row1, row2 ) )
#define min3( a, b, c ) min( a, min( b, c ) )
#define max3( a, b, c ) max( a, max( b, c ) )
#define INLINE
#define NO_INTERPOLATION_PREFIX nointerpolation
#define NO_INTERPOLATION_SUFFIX
#define finalDrawId input.drawId
#define PARAMS_ARG_DECL
#define PARAMS_ARG
#define floatBitsToUint(x) asuint(x)
#define uintBitsToFloat(x) asfloat(x)
#define floatBitsToInt(x) asint(x)
#define fract frac
#define lessThan( a, b ) (a < b)
#define inVs_vertexId input.vertexId
#define inVs_vertex input.vertex
#define inVs_blendWeights input.blendWeights
#define inVs_blendIndices input.blendIndices
#define inVs_qtangent input.qtangent
#define inVs_drawId input.drawId
#define inVs_uv0 input.uv0
#define outVs_Position outVs.gl_Position
#define outVs_clipDistance0 outVs.gl_ClipDistance0
#define gl_SampleMaskIn0 gl_SampleMask
#define interpolateAtSample( interp, subsample ) EvaluateAttributeAtSample( interp, subsample )
#define findLSB firstbitlow
#define outPs_colour0 outPs.colour0
#define OGRE_Sample( tex, sampler, uv ) tex.Sample( sampler, uv )
#define OGRE_SampleLevel( tex, sampler, uv, lod ) tex.SampleLevel( sampler, uv, lod )
#define OGRE_SampleArray2D( tex, sampler, uv, arrayIdx ) tex.Sample( sampler, float3( uv, arrayIdx ) )
#define OGRE_SampleArray2DLevel( tex, sampler, uv, arrayIdx, lod ) tex.SampleLevel( sampler, float3( uv, arrayIdx ), lod )
#define OGRE_SampleArrayCubeLevel( tex, sampler, uv, arrayIdx, lod ) tex.SampleLevel( sampler, float4( uv, arrayIdx ), lod )
#define OGRE_SampleGrad( tex, sampler, uv, ddx, ddy ) tex.SampleGrad( sampler, uv, ddx, ddy )
#define OGRE_SampleArray2DGrad( tex, sampler, uv, arrayIdx, ddx, ddy ) tex.SampleGrad( sampler, float3( uv, arrayIdx ), ddx, ddy )
#define OGRE_ddx( val ) ddx( val )
#define OGRE_ddy( val ) ddy( val )
#define OGRE_Load2D( tex, iuv, lod ) tex.Load( int3( iuv, lod ) )
#define OGRE_Load2DMS( tex, iuv, subsample ) tex.Load( iuv, subsample )
#define bufferFetch( buffer, idx ) buffer.Load( idx )
#define bufferFetch1( buffer, idx ) buffer.Load( idx ).x
#define CONST_BUFFER( bufferName, bindingPoint ) cbuffer bufferName : register(b##bindingPoint)
#define CONST_BUFFER_STRUCT_BEGIN( structName, bindingPoint ) cbuffer structName : register(b##bindingPoint) { struct _##structName
#define CONST_BUFFER_STRUCT_END( variableName ) variableName; }
#define FLAT_INTERPOLANT( decl, bindingPoint ) nointerpolation decl : TEXCOORD##bindingPoint
#define INTERPOLANT( decl, bindingPoint ) decl : TEXCOORD##bindingPoint
#define UV_DIFFUSE(x) (x)
#define UV_NORMAL(x) (x)
#define UV_SPECULAR(x) (x)
#define UV_ROUGHNESS(x) (x)
#define UV_DETAIL_WEIGHT(x) (x)
#define UV_DETAIL0(x) (x)
#define UV_DETAIL1(x) (x)
#define UV_DETAIL2(x) (x)
#define UV_DETAIL3(x) (x)
#define UV_DETAIL_NM0(x) (x)
#define UV_DETAIL_NM1(x) (x)
#define UV_DETAIL_NM2(x) (x)
#define UV_DETAIL_NM3(x) (x)
#define UV_EMISSIVE(x) (x)
#define float_fresnel float
#define make_float_fresnel( x ) x
#define OGRE_DEPTH_CMP_GE( a, b ) (a) <= (b)
#define OGRE_DEPTH_DEFAULT_CLEAR 0.0
struct PixelData
{
float3 normal;
#define geomNormal normal
float4 diffuse;
float3 specular;
float roughness;
float_fresnel F0;
float3 viewDir;
float NdotV;
};
#define SampleDetailWeightMap( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2D( tex, sampler, uv, arrayIdx )
#define SampleDetailCol0( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2D( tex, sampler, uv, arrayIdx )
#define SampleRoughness( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2D( tex, sampler, uv, arrayIdx )
//Default BRDF
INLINE float3 BRDF( float3 lightDir, float3 lightDiffuse, float3 lightSpecular, PixelData pixelData )
{
float3 halfWay = normalize( lightDir + pixelData.viewDir );
float NdotL = saturate( dot( pixelData.normal, lightDir ) );
float NdotH = saturate( dot( pixelData.normal, halfWay ) );
float VdotH = saturate( dot( pixelData.viewDir, halfWay ) );
float sqR = pixelData.roughness * pixelData.roughness;
//Roughness/Distribution/NDF term (GGX)
//Formula:
// Where alpha = roughness
// R = alpha^2 / [ PI * [ ( NdotH^2 * (alpha^2 - 1) ) + 1 ]^2 ]
float f = ( NdotH * sqR - NdotH ) * NdotH + 1.0;
float R = sqR / (f * f + 1e-6f);
//Geometric/Visibility term (Smith GGX Height-Correlated)
float Lambda_GGXV = NdotL * sqrt( (-pixelData.NdotV * sqR + pixelData.NdotV) * pixelData.NdotV + sqR );
float Lambda_GGXL = pixelData.NdotV * sqrt( (-NdotL * sqR + NdotL) * NdotL + sqR );
float G = 0.5 / (( Lambda_GGXV + Lambda_GGXL + 1e-6f ) * 3.141592654);
//Formula:
// fresnelS = lerp( (1 - V*H)^5, 1, F0 )
float_fresnel fresnelS = pixelData.F0 + pow( 1.0 - VdotH, 5.0 ) * (1.0 - pixelData.F0);
//We should divide Rs by PI, but it was done inside G for performance
float3 Rs = ( fresnelS * (R * G) ) * pixelData.specular.xyz * lightSpecular;
//Diffuse BRDF (*Normalized* Disney, see course_notes_moving_frostbite_to_pbr.pdf
//"Moving Frostbite to Physically Based Rendering" Sebastien Lagarde & Charles de Rousiers)
float energyBias = pixelData.roughness * 0.5;
float energyFactor = lerp( 1.0, 1.0 / 1.51, pixelData.roughness );
float fd90 = energyBias + 2.0 * VdotH * VdotH * pixelData.roughness;
float lightScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - NdotL, 5.0 );
float viewScatter = 1.0 + (fd90 - 1.0) * pow( 1.0 - pixelData.NdotV, 5.0 );
float fresnelD = 1.0f - fresnelS;
//We should divide Rd by PI, but it is already included in kD
float3 Rd = (lightScatter * viewScatter * energyFactor * fresnelD) * pixelData.diffuse.xyz * lightDiffuse;
return NdotL * (Rs + Rd);
}
// START UNIFORM DECLARATION
struct ShadowReceiverData
{
float4x4 texViewProj;
float2 shadowDepthRange;
float2 padding;
float4 invShadowMapSize;
};
struct Light
{
float4 position; //.w contains the objLightMask
float4 diffuse; //.w contains numNonCasterDirectionalLights
float3 specular;
float3 attenuation;
//Spotlights:
// spotDirection.xyz is direction
// spotParams.xyz contains falloff params
float4 spotDirection;
float4 spotParams;
};
#define numNonCasterDirectionalLights lights[0].diffuse.w
#define areaLightDiffuseMipmapStart areaApproxLights[0].diffuse.w
#define areaLightNumMipmapsSpecFactor areaApproxLights[0].specular.w
#define numAreaApproxLights areaApproxLights[0].doubleSided.y
#define numAreaApproxLightsWithMask areaApproxLights[0].doubleSided.z
#define numAreaLtcLights areaLtcLights[0].points[0].w
struct AreaLight
{
float4 position; //.w contains the objLightMask
float4 diffuse; //[0].w contains diffuse mipmap start
float4 specular; //[0].w contains mipmap scale
float4 attenuation; //.w contains texture array idx
//Custom 2D Shape:
// direction.xyz direction
// direction.w invHalfRectSize.x
// tangent.xyz tangent
// tangent.w invHalfRectSize.y
float4 direction;
float4 tangent;
float4 doubleSided; //.y contains numAreaApproxLights
//.z contains numAreaApproxLightsWithMask
};
struct AreaLtcLight
{
float4 position; //.w contains the objLightMask
float4 diffuse; //.w contains attenuation range
float4 specular; //.w contains doubleSided
float4 points[4]; //.w contains numAreaLtcLights
};
//Uniforms that change per pass
CONST_BUFFER_STRUCT_BEGIN( PassBuffer, 0 )
{
//Vertex shader (common to both receiver and casters)
float4x4 viewProj;
//Vertex shader
float4x4 view;
ShadowReceiverData shadowRcv[3];
//-------------------------------------------------------------------------
//Pixel shader
float3x3 invViewMatCubemap;
float padding; //Compatibility with GLSL
float pssmSplitPoints0;
float pssmSplitPoints1;
float pssmSplitPoints2;
float pssmBlendPoints0;
float pssmBlendPoints1;
float pssmFadePoint; Light lights[1]; AreaLtcLight areaLtcLights[2];
}
CONST_BUFFER_STRUCT_END( passBuf );
//Uniforms that change per Item/Entity, but change very infrequently
struct Material
{
/* kD is already divided by PI to make it energy conserving.
(formula is finalDiffuse = NdotL * surfaceDiffuse / PI)
*/
float4 bgDiffuse;
float4 kD; //kD.w is alpha_test_threshold
float4 kS; //kS.w is roughness
//Fresnel coefficient, may be per colour component (float3) or scalar (float)
//F0.w is transparency
float4 F0;
float4 normalWeights;
float4 cDetailWeights;
float4 detailOffsetScale[4];
float4 emissive; //emissive.w contains mNormalMapWeight.
float4 userValue[3];
uint4 indices0_3;
uint4 indices4_7;
};
CONST_BUFFER( MaterialBuf, 1 )
{
Material materialArray[2];
};
//Uniforms that change per Item/Entity
CONST_BUFFER( InstanceBuffer, 2 )
{
//.x =
//The lower 9 bits contain the material's start index.
//The higher 23 bits contain the world matrix start index.
//
//.y =
//shadowConstantBias. Send the bias directly to avoid an
//unnecessary indirection during the shadow mapping pass.
//Must be loaded with uintBitsToFloat
//
//.z =
//lightMask. Ogre must have been compiled with OGRE_NO_FINE_LIGHT_MASK_GRANULARITY
uint4 worldMaterialIdx[2];
};
// END UNIFORM DECLARATION
struct PS_INPUT
{
FLAT_INTERPOLANT( ushort drawId, 0 );
INTERPOLANT( float3 pos, 1 );
INTERPOLANT( float3 normal, 2 );
INTERPOLANT( float2 uv0, 3 );
INTERPOLANT( float4 posL0, 4 );
INTERPOLANT( float4 posL1, 5 );
INTERPOLANT( float4 posL2, 6 ); INTERPOLANT( float depth, 7 );
};
Texture2DArray textureMaps0 : register(t3);
Texture2DArray textureMaps1 : register(t4);
SamplerState samplerState3 : register(s3);
#define hlms_shadowmap0 texShadowMap0
#define hlms_shadowmap0_uv_min float2( 0.0, 0.0 )
#define hlms_shadowmap0_uv_max float2( 1.0, 0.28571 )
#define hlms_shadowmap0_uv_param , hlms_shadowmap0_uv_min, hlms_shadowmap0_uv_max
#define hlms_shadowmap1 texShadowMap0
#define hlms_shadowmap1_uv_min float2( 0.0, 0.28571 )
#define hlms_shadowmap1_uv_max float2( 0.50000, 0.42857 )
#define hlms_shadowmap1_uv_param , hlms_shadowmap1_uv_min, hlms_shadowmap1_uv_max
#define hlms_shadowmap2 texShadowMap0
#define hlms_shadowmap2_uv_min float2( 0.50000, 0.28571 )
#define hlms_shadowmap2_uv_max float2( 1.0, 0.42857 )
#define hlms_shadowmap2_uv_param , hlms_shadowmap2_uv_min, hlms_shadowmap2_uv_max
#define OGRE_SAMPLE_SHADOW( tex, sampler, uv, depth ) (OGRE_DEPTH_CMP_GE( depth, OGRE_DEPTH_DEFAULT_CLEAR ) ? 1.0 : tex.SampleCmpLevelZero( sampler, uv.xy, depth ).x)
#define OGRE_SAMPLE_SHADOW_ESM( tex, sampler, uv ) tex.SampleLevel( sampler, uv, 0 ).x
#define PASSBUF_ARG_DECL
#define PASSBUF_ARG
SamplerComparisonState shadowSampler: register(s2);
Texture2D<float> texShadowMap0 : register(t2);
INLINE float getShadow( Texture2D<float> shadowMap, SamplerComparisonState shadowSampler,
float4 psPosLN, float4 invShadowMapSize )
{
//Spot and directional lights
float fDepth = psPosLN.z / psPosLN.w;
float2 uv = float2( psPosLN.xy / psPosLN.w );
float retVal = 0;
float2 offsets[4] =
{
float2( 0, 0 ), //0, 0
float2( 1, 0 ), //1, 0
float2( 0, 1 ), //1, 1
float2(-1, 0 ) //0, 1
};
uv += offsets[0] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[1] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[2] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[3] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
retVal *= 0.25;
///! exponential_shadow_maps
///! exponential_shadow_maps
return retVal;
}
INLINE float getShadow( Texture2D<float> shadowMap, SamplerComparisonState shadowSampler,
float4 psPosLN, float4 invShadowMapSize, float2 minUV, float2 maxUV )
{
//Spot and directional lights
float fDepth = psPosLN.z / psPosLN.w;
float2 uv = float2( psPosLN.xy / psPosLN.w );
float retVal = 0;
float2 offsets[4] =
{
float2( 0, 0 ), //0, 0
float2( 1, 0 ), //1, 0
float2( 0, 1 ), //1, 1
float2(-1, 0 ) //0, 1
};
uv += offsets[0] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[1] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[2] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[3] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
retVal *= 0.25;
///! exponential_shadow_maps
///! exponential_shadow_maps
retVal = (uv.x <= minUV.x || uv.x >= maxUV.x ||
uv.y <= minUV.y || uv.y >= maxUV.y) ? 1.0 : retVal;
return retVal;
}
INLINE float getShadowPoint( Texture2D<float> shadowMap, SamplerComparisonState shadowSampler,
float3 posVS, float3 lightPos, float4 invShadowMapSize, float2 invDepthRange
PASSBUF_ARG_DECL )
{
//Point lights
float3 cubemapDir = posVS.xyz - lightPos.xyz;
float fDepth = length( cubemapDir );
cubemapDir *= 1.0 / fDepth;
cubemapDir = mul( cubemapDir.xyz, passBuf.invViewMatCubemap );
fDepth = (invDepthRange.x - fDepth) * invDepthRange.y;
float2 uv;
uv.x = (cubemapDir.x / (1.0 + abs( cubemapDir.z ))) * 0.25 +
(cubemapDir.z < 0.0 ? 0.75 : 0.25 );
uv.y = (cubemapDir.y / (1.0 + abs( cubemapDir.z ))) * 0.5 + 0.5;
float retVal = 0;
float2 offsets[4] =
{
float2( 0, 0 ), //0, 0
float2( 1, 0 ), //1, 0
float2( 0, 1 ), //1, 1
float2(-1, 0 ) //0, 1
};
uv += offsets[0] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[1] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[2] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[3] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
retVal *= 0.25;
///! exponential_shadow_maps
///! exponential_shadow_maps
return retVal;
}
INLINE float getShadowPoint( Texture2D<float> shadowMap, SamplerComparisonState shadowSampler,
float3 posVS, float3 lightPos, float4 invShadowMapSize, float2 invDepthRange,
float2 minUV, float2 maxUV, float2 lengthUV
PASSBUF_ARG_DECL )
{
//Point lights
float3 cubemapDir = posVS.xyz - lightPos.xyz;
float fDepth = length( cubemapDir );
cubemapDir *= 1.0 / fDepth;
cubemapDir = mul( cubemapDir.xyz, passBuf.invViewMatCubemap );
fDepth = (invDepthRange.x - fDepth) * invDepthRange.y;
float2 uv;
uv.x = (cubemapDir.x / (1.0 + abs( cubemapDir.z ))) * 0.25 +
(cubemapDir.z < 0.0 ? 0.75 : 0.25 );
uv.y = (cubemapDir.y / (1.0 + abs( cubemapDir.z ))) * 0.5 + 0.5;
uv.xy = uv.xy * lengthUV.xy + minUV.xy;
float retVal = 0;
float2 offsets[4] =
{
float2( 0, 0 ), //0, 0
float2( 1, 0 ), //1, 0
float2( 0, 1 ), //1, 1
float2(-1, 0 ) //0, 1
};
uv += offsets[0] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[1] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[2] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
uv += offsets[3] * invShadowMapSize.xy; retVal += OGRE_SAMPLE_SHADOW( shadowMap, shadowSampler, uv, fDepth );
retVal *= 0.25;
///! exponential_shadow_maps
///! exponential_shadow_maps
retVal = (uv.x <= minUV.x || uv.x >= maxUV.x ||
uv.y <= minUV.y || uv.y >= maxUV.y) ? 1.0 : retVal;
return retVal;
}
Texture2DArray<float4> ltcMatrix : register(t1);
SamplerState ltcSampler : register(s1);
#define LUT_SIZE 64.0
#define LUT_SCALE ((LUT_SIZE - 1.0)/LUT_SIZE)
#define LUT_BIAS (0.5/LUT_SIZE)
INLINE float3 IntegrateEdgeVec( float3 v1, float3 v2 )
{
float x = dot(v1, v2);
float y = abs(x);
float a = 0.8543985 + (0.4965155 + 0.0145206*y)*y;
float b = 3.4175940 + (4.1616724 + y)*y;
float v = a / b;
float theta_sintheta = (x > 0.0) ? v : 0.5*rsqrt(max(1.0 - x*x, 1e-7)) - v;
return cross( v1, v2 ) * theta_sintheta;
}
INLINE float IntegrateEdge( float3 v1, float3 v2 )
{
return IntegrateEdgeVec( v1, v2 ).z;
}
INLINE void ClipQuadToHorizon( inout float3 L[5], out int n )
{
// detect clipping config
int config = 0;
if (L[0].z > 0.0) config += 1;
if (L[1].z > 0.0) config += 2;
if (L[2].z > 0.0) config += 4;
if (L[3].z > 0.0) config += 8;
// clip
n = 0;
if (config == 0)
{
// clip all
}
else if (config == 1) // V1 clip V2 V3 V4
{
n = 3;
L[1] = -L[1].z * L[0] + L[0].z * L[1];
L[2] = -L[3].z * L[0] + L[0].z * L[3];
}
else if (config == 2) // V2 clip V1 V3 V4
{
n = 3;
L[0] = -L[0].z * L[1] + L[1].z * L[0];
L[2] = -L[2].z * L[1] + L[1].z * L[2];
}
else if (config == 3) // V1 V2 clip V3 V4
{
n = 4;
L[2] = -L[2].z * L[1] + L[1].z * L[2];
L[3] = -L[3].z * L[0] + L[0].z * L[3];
}
else if (config == 4) // V3 clip V1 V2 V4
{
n = 3;
L[0] = -L[3].z * L[2] + L[2].z * L[3];
L[1] = -L[1].z * L[2] + L[2].z * L[1];
}
else if (config == 5) // V1 V3 clip V2 V4) impossible
{
n = 0;
}
else if (config == 6) // V2 V3 clip V1 V4
{
n = 4;
L[0] = -L[0].z * L[1] + L[1].z * L[0];
L[3] = -L[3].z * L[2] + L[2].z * L[3];
}
else if (config == 7) // V1 V2 V3 clip V4
{
n = 5;
L[4] = -L[3].z * L[0] + L[0].z * L[3];
L[3] = -L[3].z * L[2] + L[2].z * L[3];
}
else if (config == 8) // V4 clip V1 V2 V3
{
n = 3;
L[0] = -L[0].z * L[3] + L[3].z * L[0];
L[1] = -L[2].z * L[3] + L[3].z * L[2];
L[2] = L[3];
}
else if (config == 9) // V1 V4 clip V2 V3
{
n = 4;
L[1] = -L[1].z * L[0] + L[0].z * L[1];
L[2] = -L[2].z * L[3] + L[3].z * L[2];
}
else if (config == 10) // V2 V4 clip V1 V3) impossible
{
n = 0;
}
else if (config == 11) // V1 V2 V4 clip V3
{
n = 5;
L[4] = L[3];
L[3] = -L[2].z * L[3] + L[3].z * L[2];
L[2] = -L[2].z * L[1] + L[1].z * L[2];
}
else if (config == 12) // V3 V4 clip V1 V2
{
n = 4;
L[1] = -L[1].z * L[2] + L[2].z * L[1];
L[0] = -L[0].z * L[3] + L[3].z * L[0];
}
else if (config == 13) // V1 V3 V4 clip V2
{
n = 5;
L[4] = L[3];
L[3] = L[2];
L[2] = -L[1].z * L[2] + L[2].z * L[1];
L[1] = -L[1].z * L[0] + L[0].z * L[1];
}
else if (config == 14) // V2 V3 V4 clip V1
{
n = 5;
L[4] = -L[0].z * L[3] + L[3].z * L[0];
L[0] = -L[0].z * L[1] + L[1].z * L[0];
}
else if (config == 15) // V1 V2 V3 V4
{
n = 4;
}
if (n == 3)
L[3] = L[0];
if (n == 4)
L[4] = L[0];
}
INLINE float LTC_Evaluate( float3 N, float3 V, float3 P, float3x3 Minv,
float4 points[4],
bool twoSided )
{
// construct orthonormal basis around N
float3 T1, T2;
T1 = normalize( V - N*dot(V, N) );
T2 = cross(N, T1);
// rotate area light in (T1, T2, N) basis
Minv = mul( Minv, transpose( buildFloat3x3( T1, T2, N ) ) );
// polygon (allocate 5 vertices for clipping)
float3 L[5];
L[0] = mul( Minv, points[0].xyz - P );
L[1] = mul( Minv, points[1].xyz - P );
L[2] = mul( Minv, points[2].xyz - P );
L[3] = mul( Minv, points[3].xyz - P );
// integrate
float sum = 0.0;
int n;
ClipQuadToHorizon( L, n );
if( n == 0 )
return 0;
// project onto sphere
L[0] = normalize( L[0] );
L[1] = normalize( L[1] );
L[2] = normalize( L[2] );
L[3] = normalize( L[3] );
L[4] = normalize( L[4] );
// integrate
sum += IntegrateEdge( L[0], L[1] );
sum += IntegrateEdge( L[1], L[2] );
sum += IntegrateEdge( L[2], L[3] );
if( n >= 4 )
sum += IntegrateEdge( L[3], L[4] );
if( n == 5 )
sum += IntegrateEdge( L[4], L[0] );
sum = twoSided ? abs(sum) : max(0.0, sum);
return sum;
}
struct PS_OUTPUT
{
float4 colour0 : SV_Target0;
};
PS_OUTPUT main
(
PS_INPUT inPs
)
{
PS_OUTPUT outPs;
PixelData pixelData;
ushort materialId = worldMaterialIdx[inPs.drawId].x & 0x1FFu;
#define material materialArray[materialId]
ushort texIndex_detailMapIdx0 = material.indices0_3.z >> 16u;
ushort texIndex_roughnessIdx = material.indices0_3.y >> 16u;
//Prepare weight map for the detail maps.
float4 detailWeights = float4( 1.0, 1.0, 1.0, 1.0 );
/// Sample detail maps and weight them against the weight map in the next foreach loop.
float4 detailCol0 = SampleDetailCol0( textureMaps1,
samplerState3,
UV_DETAIL0( inPs.uv0.xy * material.detailOffsetScale[0].zw + material.detailOffsetScale[0].xy ),
texIndex_detailMapIdx0 );
detailWeights.x *= detailCol0.w;
detailCol0.w = detailWeights.x;
/// DIFFUSE MAP
/// If there are no diffuse maps, we must initialize it to some value.
pixelData.diffuse.xyzw = material.bgDiffuse.xyzw;
/// Blend the detail diffuse maps with the main diffuse.
//Normal Non Premultiplied 0
pixelData.diffuse.xyz = lerp( pixelData.diffuse.xyz, detailCol0.xyz, detailCol0.a );
pixelData.diffuse.w = lerp( pixelData.diffuse.w, 1.0, detailCol0.w );
/// Apply the material's diffuse over the textures
pixelData.diffuse.xyz *= material.kD.xyz;
/// SPECUlAR MAP
pixelData.specular.xyz = material.kS.xyz;
pixelData.F0 = material.F0.x;
/// ROUGHNESS MAP
pixelData.roughness = material.kS.w;
pixelData.roughness *= SampleRoughness( textureMaps0,
samplerState3,
UV_ROUGHNESS( inPs.uv0.xy ),
texIndex_roughnessIdx ).x;
pixelData.roughness = max( pixelData.roughness, 0.001f );
// Geometric normal
pixelData.normal = normalize( inPs.normal ) ;
/// If there is no normal map, the first iteration must
/// initialize pixelData.normal instead of try to merge with it.
/// Blend the detail normal maps with the main normal.
float fShadow = 1.0;
float fShadowBlend = 1.0;
if( inPs.depth <= passBuf.pssmSplitPoints0 )
{
fShadow = getShadow( hlms_shadowmap0, shadowSampler,
inPs.posL0,
passBuf.shadowRcv[0].invShadowMapSize
hlms_shadowmap0_uv_param );
if( inPs.depth > passBuf.pssmBlendPoints0 )
{
fShadowBlend = getShadow( hlms_shadowmap1, shadowSampler,
inPs.posL1,
passBuf.shadowRcv[1].invShadowMapSize
hlms_shadowmap1_uv_param );
fShadow = lerp( fShadow, fShadowBlend,
(inPs.depth - passBuf.pssmBlendPoints0) /
(passBuf.pssmSplitPoints0 - passBuf.pssmBlendPoints0) );
}
}
else if( inPs.depth <= passBuf.pssmSplitPoints1 )
{
fShadow = getShadow( hlms_shadowmap1, shadowSampler,
inPs.posL1,
passBuf.shadowRcv[1].invShadowMapSize
hlms_shadowmap1_uv_param );
if( inPs.depth > passBuf.pssmBlendPoints1 )
{
fShadowBlend = getShadow( hlms_shadowmap2, shadowSampler,
inPs.posL2,
passBuf.shadowRcv[2].invShadowMapSize
hlms_shadowmap2_uv_param );
fShadow = lerp( fShadow, fShadowBlend,
(inPs.depth - passBuf.pssmBlendPoints1) /
(passBuf.pssmSplitPoints1 - passBuf.pssmBlendPoints1) );
}
}
else if( inPs.depth <= passBuf.pssmSplitPoints2 )
{
fShadow = getShadow( hlms_shadowmap2, shadowSampler,
inPs.posL2,
passBuf.shadowRcv[2].invShadowMapSize
hlms_shadowmap2_uv_param );
if( inPs.depth > passBuf.pssmFadePoint )
{
fShadow = lerp( fShadow, 1.0,
(inPs.depth - passBuf.pssmFadePoint) /
(passBuf.pssmSplitPoints2 - passBuf.pssmFadePoint) );
}
}
//Everything's in Camera space
pixelData.viewDir = normalize( -inPs.pos );
pixelData.NdotV = saturate( dot( pixelData.normal, pixelData.viewDir ) );
float3 finalColour = float3(0, 0, 0);
float3 lightDir;
float fDistance;
float3 tmpColour;
float spotCosAngle;
finalColour += BRDF( passBuf.lights[0].position.xyz, passBuf.lights[0].diffuse.xyz, passBuf.lights[0].specular, pixelData ) * fShadow;
for( int i=0; i<floatBitsToInt( passBuf.numAreaLtcLights ); ++i )
{
lightDir = passBuf.areaLtcLights[i].position.xyz - inPs.pos;
fDistance = length( lightDir );
if( fDistance <= passBuf.areaLtcLights[i].diffuse.w )
{
float2 ltcUV = float2( pixelData.roughness, sqrt(1.0 - pixelData.NdotV) );
ltcUV = ltcUV * LUT_SCALE + LUT_BIAS;
float4 ltc0 = OGRE_SampleArray2DLevel( ltcMatrix, ltcSampler, ltcUV, 0, 0 );
float4 ltc1 = OGRE_SampleArray2DLevel( ltcMatrix, ltcSampler, ltcUV, 1, 0 );
float3x3 Minv = buildFloat3x3(
float3(ltc0.x, 0, ltc0.y),
float3( 0, 1, 0),
float3(ltc0.z, 0, ltc0.w)
);
bool doubleSidedLtc = passBuf.areaLtcLights[i].specular.w != 0.0f;
float ltcSpecular = LTC_Evaluate( pixelData.normal.xyz, pixelData.viewDir.xyz, inPs.pos.xyz, Minv,
passBuf.areaLtcLights[i].points, doubleSidedLtc );
// BRDF shadowing and Fresnel
ltcSpecular *= pixelData.F0 * ltc1.x + (1.0 - pixelData.F0) * ltc1.y;
float ltcDiffuse = LTC_Evaluate( pixelData.normal.xyz, pixelData.viewDir.xyz, inPs.pos.xyz,
buildFloat3x3( float3( 1, 0, 0 ), float3( 0, 1, 0 ), float3( 0, 0, 1 ) ),
passBuf.areaLtcLights[i].points, doubleSidedLtc );
finalColour += passBuf.areaLtcLights[i].diffuse.xyz * ltcDiffuse * pixelData.diffuse.xyz;
finalColour += passBuf.areaLtcLights[i].specular.xyz * ltcSpecular * pixelData.specular.xyz;
}
}
///!hlms_prepass
///!hlms_normal || hlms_qtangent
outPs_colour0.xyz = finalColour;
outPs_colour0.w = 1.0;
return outPs;
}