arg sorry. I tested so much, that i got confused.
PlanetTerraDefaultMaterial json loaded at startup, datablock assigned to item by
name only — no C++ setTexture() calls whatsoever for the NM slots.
MATERIAL: base diffuse + base normal (BC5_SNORM) + detail_weight + 4x detail_diffuse
(jpg, NormalNonPremul) + 4x detail_normal (BC5_SNORM DDS, all different files,
same resolution).
Works fine with detail_diffuse only. Crashes as soon as detail_normal0..3 are
defined in the JSON.
All four BC5_SNORM DDS textures collapse to the same pool slot. HLMS then only
inlines SampleDetailMapNm0 — SampleDetailMapNm1/2/3 are emitted as raw @piece()
definition headers literally into the HLSL output, causing:
Code: Select all
#if 0
*** textureMaps3 6
*** hlms_uv_count0 2
*** hlms_pose 0
*** uv_emissive 0
*** textureMaps4 7
*** first_valid_detail_map_nm 0
*** fresnel_scalar 0
*** hlms_shadowmap2_uv_max_y 1054567864
*** envprobe_map_sampler 3
*** hlms_uv_count 2
*** detail_map1 1
*** pcf_iterations 4
*** uv_detail_nm1 0
*** uv_detail_nm2 0
*** envMapRegSampler 3
*** emissive_map_sampler 3
*** hlms_tex_gather 1
*** precision_mode -2126167738
*** hlms_shadowmap2_array_idx 0
*** set0_texture_slot_end 3
*** uv_specular 0
*** hlms_disable_stage 0
*** NumPoseWeightVectors 0
*** hlms_shadowmap1_uv_min_x 0
*** specular_map_sampler 3
*** hlms_shadowmap0_uv_min_y 0
*** texcoord 11
*** fast_shader_build_hack 1
*** glsl 635204550
*** normal_weight_tex 1
*** normal_sampling_format -1392068498
*** hlms_uv_count1 2
*** NumPoseWeightVectorsB 0
*** detail_map2 1
*** hlms_num_shadow_map_lights 3
*** hlms_lights_directional 1
*** samplerStateStart 3
*** detail_map3 1
*** alpha_test 0
*** roughness_map_sampler 3
*** detail_weight_map 3
*** hlms_shadowmap2 0
*** hlms_shadowmap0_light_idx 0
*** StrongMacroblockBits 0
*** metallic_workflow 0
*** detail_map_nm1 5
*** hw_gamma_write 1
*** uv_detail_weight 0
*** detail_map_nm0_idx 4
*** detail_map_nm2_sampler 3
*** hlms_shadowmap1_uvs_fulltex 1
*** hlms_alpha_to_coverage 0
*** cubemaps_as_diffuse_gi 1
*** hlms_shadowmap2_uv_min_y 1049774373
*** uv_detail_nm3 0
*** NumPoseWeightVectorsC 0
*** hlms_pssm_splits 3
*** ambient_hemisphere_inverted 1
*** hlms_pose_normals 0
*** target_envprobe_map 1
*** hlms_pose_half 0
*** hlms_shadowmap1_light_idx 0
*** hlms_lights_spot 1
*** shadowmap2_is_directional_light 1
*** hlms_shadowmap1_uv_max_x 1056964608
*** hlms_shadowmap0_uv_min_x 0
*** detail_map1_sampler 3
*** uv_normal 0
*** relaxed 1726237731
*** hlms_shadowmap1_uv_min_y 1049774373
*** detail_map_nm3_sampler 3
*** hlms_alphablend 0
*** textureMaps2 5
*** detail_maps_normal 4
*** hlms_num_shadow_map_textures 1
*** detail_map_nm1_idx 4
*** hlms_view_matrix 1
*** MoreThanOnePose -1
*** hlms_shadowmap1_array_idx 0
*** detail_map0 4
*** num_textures 5
*** hlslvk 1841745752
*** normal_map_tex 2
*** uv_detail3 0
*** detail_maps_diffuse 4
*** hlms_shadow_uses_depth_texture 1
*** hlms_msaa_samples 1
*** ltcMatrix 1
*** detail_map3_sampler 3
*** hlms_shadowmap0_uv_max_x 1065353216
*** normal_map 1
*** hlms_tangent 1
*** hlms_shadowmap1 0
*** needs_env_brdf 1
*** NumPoseWeightVectorsA 0
*** pcf 3
*** uv_detail1 0
*** fresnel_workflow 1
*** shadowmap1_is_directional_light 1
*** full32 -2126167738
*** detail_map_nm0 5
*** detail_map_nm3_idx 4
*** perceptual_roughness 1
*** alpha_test_shadow_caster_only 0
*** materials_per_buffer 2
*** hw_gamma_read 1
*** normal_map_tex_idx 1
*** detail_weight_map_idx 2
*** hlms_skeleton 0
*** hlms_pssm_splits_minus_one 2
*** midf16 -1978079318
*** partial_pso_clip_distances 0
*** syntax -334286542
*** hlms_lights_point 1
*** diffuse_map_sampler 3
*** hlms_tangent4 1
*** hlms_fine_light_mask 1
*** metal -1698855755
*** fresnel_has_diffuse 1
*** detail_map_nm1_sampler 3
*** s_lights_directional_non_caster 1
*** uv_detail0 0
*** uv_diffuse 0
*** diffuse_map 1
*** needs_refl_dir 1
*** hlms_pssm_blend 1
*** uv_detail_nm0 0
*** detail_weight_map_sampler 3
*** detail_offsets3 1
*** detail_offsets0 1
*** normal_rg_snorm -1392068498
*** diffuse_map_idx 0
*** detail_map_nm0_sampler 3
*** hlms_shadowmap2_uv_max_x 1065353216
*** hlms_shadowmap1_uv_max_y 1054567864
*** hlms_shadowmap2_light_idx 0
*** shadowmap0_is_directional_light 1
*** hlms_shadowmap0_array_idx 0
*** hlms_render_depth_only 0
*** num_pass_const_buffers 4
*** normal_map_tex_sampler 3
*** uv_detail2 0
*** MoreThanOnePoseWeightVector -1
*** detail_map2_sampler 3
*** full_pso_clip_distances 0
*** textureMaps0 3
*** detail_map_nm3 5
*** hlms_shadowmap0_uvs_fulltex 1
*** detail_map0_sampler 3
*** hlms_shadowmap2_uv_min_x 1056964608
*** uv_roughness 0
*** receive_shadows 1
*** detail_offsets2 1
*** textureMaps1 4
*** detail_map3_idx 0
*** hlms_pssm_fade 1
*** hlms_shadowmap0 0
*** detail_map0_idx 3
*** needs_view_dir 1
*** detail_map_nm2 5
*** detail_map2_idx 0
*** hlms_shadowmap2_uvs_fulltex 1
*** BRDF_CookTorrance 1
*** detail_map1_idx 0
*** set1_texture_slot_end 8
*** use_planar_reflections 0
*** detail_map_nm2_idx 4
*** texShadowMap0 2
*** ambient_hemisphere 1
*** hlms_normal 1
*** ltc_texture_available 1
*** num_samplers 1
*** glslvk -338983575
*** hlsl -334286542
*** hlms_shadowmap0_uv_max_y 1049774373
*** detail_offsets1 1
*** normal_weight 1
DONE DUMPING PROPERTIES
*** blend_mode_idx3 @insertpiece( NormalNonPremul)
*** hlms_shadowmap2_uv_max_y 0.428571
*** hlms_shadowmap1_uv_min_x 0.000000
*** hlms_shadowmap0_uv_min_y 0.000000
*** blend_mode_idx2 @insertpiece( NormalNonPremul)
*** hlms_shadowmap2_uv_min_y 0.285714
*** hlms_shadowmap1_uv_max_x 0.500000
*** hlms_shadowmap0_uv_min_x 0.000000
*** hlms_shadowmap1_uv_min_y 0.285714
*** hlms_shadowmap0_uv_max_x 1.000000
*** hlms_shadowmap2_uv_max_x 1.000000
*** hlms_shadowmap1_uv_max_y 0.428571
*** blend_mode_idx1 @insertpiece( NormalNonPremul)
*** hlms_shadowmap2_uv_min_x 0.500000
*** blend_mode_idx0 @insertpiece( NormalNonPremul)
*** hlms_shadowmap0_uv_max_y 0.285714
DONE DUMPING PIECES
#endif
//#include "SyntaxHighlightingMisc.h"
#define ushort uint
#define ushort3 uint3
#define ushort4 uint4
#define ogre_float4x3 float4x3
//Short used for read operations. It's an int in GLSL & HLSL. An ushort in Metal
#define rshort int
#define rshort2 int2
#define rint int
//Short used for write operations. It's an int in GLSL. An ushort in HLSL & Metal
#define wshort2 uint2
#define wshort3 uint3
#define toFloat3x3( x ) ((float3x3)(x))
#define buildFloat3x3( row0, row1, row2 ) transpose( float3x3( row0, row1, row2 ) )
#define buildFloat4x4( row0, row1, row2, row3 ) transpose( float4x4( row0, row1, row2, row3 ) )
#define getMatrixRow( mat, idx ) transpose( mat )[idx]
// See CrossPlatformSettings_piece_all.glsl for an explanation
#define _h(x) (x)
#define midf float
#define midf2 float2
#define midf3 float3
#define midf4 float4
#define midf2x2 float2x2
#define midf3x3 float3x3
#define midf4x4 float4x4
#define midf_c float
#define midf2_c float2
#define midf3_c float3
#define midf4_c float4
#define midf2x2_c float2x2
#define midf3x3_c float3x3
#define midf4x4_c float4x4
#define toMidf3x3( x ) ((float3x3)( x ))
#define buildMidf3x3( row0, row1, row2 ) transpose( float3x3( row0, row1, row2 ) )
#define ensureValidRangeF16(x)
#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 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_normal input.normal
#define inVs_tangent input.tangent
#define inVs_binormal input.binormal
#define inVs_blendWeights input.blendWeights
#define inVs_blendIndices input.blendIndices
#define inVs_qtangent input.qtangent
#define inVs_colour input.colour
#define inVs_drawId input.drawId
#define finalDrawId inVs_drawId
#define inVs_uv0 input.uv0
#define inVs_uv1 input.uv1
#define outVs_Position outVs.gl_Position
#define outVs_viewportIndex outVs.gl_ViewportIndex
#define outVs_clipDistance0 outVs.gl_ClipDistance0.x
#define gl_SampleMaskIn0 gl_SampleMask
#define interpolateAtSample( interp, subsample ) EvaluateAttributeAtSample( interp, subsample )
#define findLSB firstbitlow
#define findMSB firstbithigh
#define mod( a, b ) ( (a) - (b) * floor( (a) / (b) ) )
#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_LoadArray2D( tex, iuv, arrayIdx, lod ) tex.Load( int4( iuv, arrayIdx, lod ) )
#define OGRE_Load2DMS( tex, iuv, subsample ) tex.Load( iuv, subsample )
#define OGRE_Load3D( tex, iuv, lod ) tex.Load( int4( iuv, lod ) )
#define OGRE_Load2DF16( tex, iuv, lod ) tex.Load( int3( iuv, lod ) )
#define OGRE_Load2DMSF16( tex, iuv, subsample ) tex.Load( iuv, subsample )
#define OGRE_SampleF16( tex, sampler, uv ) tex.Sample( sampler, uv )
#define OGRE_SampleLevelF16( tex, sampler, uv, lod ) tex.SampleLevel( sampler, uv, lod )
#define OGRE_SampleArray2DF16( tex, sampler, uv, arrayIdx ) tex.Sample( sampler, float3( uv, arrayIdx ) )
#define OGRE_SampleArray2DLevelF16( tex, sampler, uv, arrayIdx, lod ) tex.SampleLevel( sampler, float3( uv, arrayIdx ), lod )
#define OGRE_SampleArrayCubeLevelF16( tex, sampler, uv, arrayIdx, lod ) tex.SampleLevel( sampler, float4( uv, arrayIdx ), lod )
#define OGRE_SampleGradF16( tex, sampler, uv, ddx, ddy ) tex.SampleGrad( sampler, uv, ddx, ddy )
#define OGRE_SampleArray2DGradF16( tex, sampler, uv, arrayIdx, ddx, ddy ) tex.SampleGrad( sampler, float3( uv, arrayIdx ), ddx, ddy )
#define bufferFetch( buffer, idx ) buffer.Load( idx )
#define bufferFetch1( buffer, idx ) buffer.Load( idx ).x
#define structuredBufferFetch( buffer, idx ) buffer[idx]
#define ReadOnlyBuffer( slot, varType, varName ) StructuredBuffer<varType> varName : register(t##slot)
#define readOnlyFetch( bufferVar, idx ) bufferVar[idx]
#define readOnlyFetch1( bufferVar, idx ) bufferVar[idx].x
#define OGRE_Texture3D_float4 Texture3D
#define OGRE_ArrayTex( declType, varName, arrayCount ) declType varName[arrayCount]
#define OGRE_SAMPLER_ARG_DECL( samplerName ) , SamplerState samplerName
#define OGRE_SAMPLER_ARG( samplerName ) , samplerName
#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 OGRE_OUT_REF( declType, variableName ) out declType variableName
#define OGRE_INOUT_REF( declType, variableName ) inout declType variableName
#define OGRE_ARRAY_START( type ) {
#define OGRE_ARRAY_END }
float4 unpackSnorm4x8( uint value )
{
int signedValue = int( value );
int4 packed = int4( signedValue << 24, signedValue << 16, signedValue << 8, signedValue ) >> 24;
return clamp( float4( packed ) / 127.0, -1.0, 1.0 );
}
float2 unpackSnorm2x16( uint value )
{
int signedValue = int( value );
int2 packed = int2( signedValue << 16, signedValue ) >> 16;
return clamp( float2( packed ) / 32767.0, -1.0, 1.0 );
}
#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)
// START UNIFORM DECLARATION
struct ShadowReceiverData
{
float4x4 texViewProj;
float2 shadowDepthRange;
float normalOffsetBias;
float padding;
float4 invShadowMapSize;
};
struct Light
{
float3 position;
uint lightMask;
float4 diffuse; //.w contains numNonCasterDirectionalLights
float3 specular;
float3 attenuation;
//Spotlights:
// spotDirection.xyz is direction
// spotParams.xyz contains falloff params
float4 spotDirection;
float4 spotParams;
#define lightTexProfileIdx spotDirection.w
};
#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
#define numAreaLtcLights areaLtcLights[0].points[0].w
struct AreaLight
{
float3 position;
uint lightMask;
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
{
float3 position;
uint lightMask;
float4 diffuse; //.w contains attenuation range
float4 specular; //.w contains doubleSided
float4 points[4]; //.w contains numAreaLtcLights
//points[1].w, points[2].w, points[3].w contain obbFadeFactorLtc.xyz
};
//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
float4 pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps;
float4 aspectRatio_planarReflNumMips_unused2;
float2 invWindowRes;
float2 windowResolution;
float4 ambientUpperHemi;
float4 ambientLowerHemi;
float4 ambientHemisphereDir;
float pssmSplitPoints0;
float pssmSplitPoints1;
float pssmSplitPoints2;
float pssmBlendPoints0;
float pssmBlendPoints1;
float pssmFadePoint;
Light lights[1]; // !use_light_buffers
#define pccVctMinDistance pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps.x
#define invPccVctInvDistance pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps.y
#define rightEyePixelStartX pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps.z
#define envMapNumMipmaps pccVctMinDistance_invPccVctInvDistance_rightEyePixelStartX_envMapNumMipmaps.w
#define aspectRatio aspectRatio_planarReflNumMips_unused2.x
#define planarReflNumMips aspectRatio_planarReflNumMips_unused2.y
}
CONST_BUFFER_STRUCT_END( passBuf );
#define light0Buf passBuf
#define light1Buf passBuf
#define light2Buf passBuf
// use_light_buffers
//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.
float refractionStrength;
float clearCoat;
float clearCoatRoughness;
float _padding1;
float4 userValue[3];
uint4 indices0_3;
uint4 indices4_7;
};
#define normalMapWeight material.emissive.w
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
#define float_fresnel midf
#define float_fresnel_c( x ) midf_c( x )
#define make_float_fresnel( x ) midf_c( x )
#define OGRE_DEPTH_CMP_GE( a, b ) (a) <= (b)
#define OGRE_DEPTH_DEFAULT_CLEAR 0.0
#define PASSBUF_ARG_DECL
#define PASSBUF_ARG
struct PixelData
{
midf3 normal;
midf3 geomNormal;
midf4 diffuse;
midf3 specular;
midf perceptualRoughness;
midf roughness;
float_fresnel F0;
midf3 viewDir;
midf NdotV;
midf3 reflDir;
midf3 envColourS;
midf3 envColourD;
};
#define SampleDetailWeightMap( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2DF16( tex, sampler, uv, arrayIdx )
#define SampleDetailCol0( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2DF16( tex, sampler, uv, arrayIdx )
#define SampleDetailCol1( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2DF16( tex, sampler, uv, arrayIdx )
#define SampleDetailCol2( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2DF16( tex, sampler, uv, arrayIdx )
#define SampleDetailCol3( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2DF16( tex, sampler, uv, arrayIdx )
#define SampleDiffuse( tex, sampler, uv, arrayIdx ) OGRE_SampleArray2DF16( tex, sampler, uv, arrayIdx )
INLINE midf3 reconstructZfromTSNormal( midf2 tsNormal2 )
{
midf3 tsNormal;
tsNormal.xy = tsNormal2.xy;
tsNormal.z = sqrt( max( _h(0.0f), _h(1.0f) - tsNormal.x * tsNormal.x - tsNormal.y * tsNormal.y ) );
return tsNormal.xyz;
}
//Normal texture must be in UV8/RG8_SNORM or BC5S format!
#define getTSNormal( normalMap, samplerState, uv, normalIdx ) reconstructZfromTSNormal( OGRE_SampleArray2DF16( normalMap, samplerState, uv, normalIdx ).xy )
//Cook-Torrance
INLINE midf3 BRDF( midf3 lightDir, midf3 lightDiffuse, midf3 lightSpecular, PixelData pixelData PASSBUF_ARG_DECL )
{
midf3 halfWay = normalize( lightDir + pixelData.viewDir );
midf NdotL = saturate( dot( pixelData.normal, lightDir ) );
midf NdotH = clamp( dot( pixelData.normal, halfWay ), _h( 0.001 ), _h( 1.0 ) );
midf VdotH = clamp( dot( pixelData.viewDir, halfWay ), _h( 0.001 ), _h( 1.0 ) );
midf sqR = pixelData.roughness * pixelData.roughness;
//Roughness/Distribution/NDF term (Beckmann distribution)
//Formula:
// Where alpha = NdotH and m = roughness
// R = [ 1 / (m^2 x cos(alpha)^4 ] x [ e^( -tan(alpha)^2 / m^2 ) ]
// R = [ 1 / (m^2 x cos(alpha)^4 ] x [ e^( ( cos(alpha)^2 - 1 ) / (m^2 cos(alpha)^2 ) ]
midf NdotH_sq = NdotH * NdotH;
midf roughness_b = NdotH_sq - _h( 1.0 ); //( cos(alpha)^2 - 1 )
midf roughness_a = _h( 1.0 ) / ( _h( 3.141592654 ) * sqR * NdotH_sq * NdotH_sq );//( 1 / (m^2 x cos(alpha)^4 )
midf roughness_c = sqR * NdotH_sq; //( m^2 cos(alpha)^2 )
//Avoid Inf * 0 = NaN; we need Inf * 0 = 0
midf R = min( roughness_a, _h( 65504.0 ) ) * exp( roughness_b / roughness_c );
ensureValidRangeF16( R );
//Geometric/Visibility term (Cook Torrance)
midf shared_geo = _h( 2.0 ) * NdotH / VdotH;
ensureValidRangeF16( shared_geo );
midf geo_b = shared_geo * pixelData.NdotV;
midf geo_c = shared_geo * NdotL;
midf G = min( _h( 1.0 ), min( geo_b, geo_c ) );
//Fresnel term (Schlick's approximation)
//Formula:
// fresnelS = lerp( (1 - V*H)^5, 1, F0 )
// fresnelD = lerp( (1 - N*L)^5, 1, 1 - F0 ) [See s2010_course_note_practical_implementation_at_triace.pdf]
float_fresnel fresnelS = pixelData.F0 + pow( _h( 1.0 ) - VdotH, _h( 5.0 ) ) * (_h( 1.0 ) - pixelData.F0);
midf fresnelD = _h( 1.0f ) - fresnelS;
//Avoid very small denominators, they go to NaN or cause aliasing artifacts
float_fresnel Rs = ( fresnelS * (R * G) ) / max( _h( 4.0 ) * pixelData.NdotV * NdotL, _h( 0.01 ) );
return NdotL * (pixelData.specular.xyz * lightSpecular * Rs +
pixelData.diffuse.xyz * lightDiffuse * fresnelD);
}
struct PS_INPUT
{
FLAT_INTERPOLANT( ushort drawId, 0 );
INTERPOLANT( float3 pos, 1 );
INTERPOLANT( midf3 normal, 2 );
INTERPOLANT( midf3 tangent, 3 );
FLAT_INTERPOLANT( midf biNormalReflection, 4 );
INTERPOLANT( float2 uv0, 5 );
INTERPOLANT( float2 uv1, 6 );
INTERPOLANT( float4 posL0, 7 );
INTERPOLANT( float4 posL1, 8 );
INTERPOLANT( float4 posL2, 9 );
INTERPOLANT( float depth, 10 );
};
Texture2DArray textureMaps0 : register(t3);
Texture2DArray textureMaps1 : register(t4);
Texture2DArray textureMaps2 : register(t5);
Texture2DArray textureMaps3 : register(t6);
Texture2DArray textureMaps4 : register(t7);
SamplerState samplerState3 : register(s3);
#define hlms_shadowmap0 texShadowMap0
#define hlms_shadowmap0_uv_min float2( 0.000000, 0.000000 )
#define hlms_shadowmap0_uv_max float2( 1.000000, 0.285714 )
#define hlms_shadowmap0_uv_param , hlms_shadowmap0_uv_min, hlms_shadowmap0_uv_max
#define hlms_shadowmap1 texShadowMap0
#define hlms_shadowmap1_uv_min float2( 0.000000, 0.285714 )
#define hlms_shadowmap1_uv_max float2( 0.500000, 0.428571 )
#define hlms_shadowmap1_uv_param , hlms_shadowmap1_uv_min, hlms_shadowmap1_uv_max
#define hlms_shadowmap2 texShadowMap0
#define hlms_shadowmap2_uv_min float2( 0.500000, 0.285714 )
#define hlms_shadowmap2_uv_max float2( 1.000000, 0.428571 )
#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 ) ? _h( 1.0 ) : midf_c( tex.SampleCmpLevelZero( sampler, uv.xy, depth ).x ))
#define OGRE_SAMPLE_SHADOW_ESM( tex, sampler, uv ) tex.SampleLevel( sampler, uv, 0 ).x
SamplerComparisonState shadowSampler: register(s2);
Texture2D<float> texShadowMap0 : register(t2);
#define inPs_posL0 inPs.posL0
#define inPs_posL1 inPs.posL1
#define inPs_posL2 inPs.posL2
// Perform normal offset bias. See https://github.com/OGRECave/ogre-next/issues/100
INLINE float3 getNormalOffsetBiasPoint( midf3 geomNormal, float3 lightDir,
float normalOffsetBias, float shadowMapTexSize,
float depthRange
)
{
float tmpNdotL = saturate( dot( lightDir.xyz, float3( geomNormal.xyz ) ) );
return ( ( 1.0f - tmpNdotL ) * normalOffsetBias * float3( geomNormal.xyz ) * shadowMapTexSize );
}
// Perform normal offset bias. See https://github.com/OGRECave/ogre-next/issues/100
INLINE float3 getNormalOffsetBiasPoint( midf3 geomNormal, float3 lightDir,
float normalOffsetBias, float shadowMapTexSize,
float depthRange
, float2 minUV, float2 maxUV )
{
float tmpNdotL = saturate( dot( lightDir.xyz, float3( geomNormal.xyz ) ) );
shadowMapTexSize /= maxUV.x - minUV.x;
return ( ( 1.0f - tmpNdotL ) * normalOffsetBias * float3( geomNormal.xyz ) * shadowMapTexSize );
}
INLINE midf 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 );
midf retVal = _h( 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 *= _h( 0.25 );
///! exponential_shadow_maps
///! exponential_shadow_maps
return retVal;
}
INLINE midf 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 );
midf retVal = _h( 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 *= _h( 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) ? _h( 1.0 ) : retVal;
return retVal;
}
INLINE midf getShadowPoint( Texture2D<float> shadowMap, SamplerComparisonState shadowSampler,
midf3 geomNormal, float normalOffsetBias,
float3 posVS, float3 lightPos,float4 invShadowMapSize, float2 invDepthRange
PASSBUF_ARG_DECL )
{
//Point lights
float3 cubemapDir = posVS.xyz - lightPos.xyz;
cubemapDir += getNormalOffsetBiasPoint( geomNormal, cubemapDir, normalOffsetBias,
invShadowMapSize.x, invDepthRange.y );
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;
midf retVal = _h( 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 *= _h( 0.25 );
///! exponential_shadow_maps
///! exponential_shadow_maps
return retVal;
}
INLINE midf getShadowPoint( Texture2D<float> shadowMap, SamplerComparisonState shadowSampler,
midf3 geomNormal, float normalOffsetBias,
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;
cubemapDir += getNormalOffsetBiasPoint( geomNormal, cubemapDir, normalOffsetBias,
invShadowMapSize.x, invDepthRange.y, minUV, maxUV );
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;
midf retVal = _h( 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 *= _h( 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) ? _h( 1.0 ) : retVal;
return retVal;
}
Texture2DArray<float4> ltcMatrix : register(t1);
SamplerState ltcSampler : register(s1);
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_diffuseIdx = material.indices0_3.x & 0x0000FFFFu;
ushort texIndex_weightMapIdx = material.indices0_3.z & 0x0000FFFFu;
ushort texIndex_detailMapIdx0 = material.indices0_3.z >> 16u;
ushort texIndex_detailMapIdx1 = material.indices0_3.w & 0x0000FFFFu;
ushort texIndex_detailMapIdx2 = material.indices0_3.w >> 16u;
ushort texIndex_detailMapIdx3 = material.indices4_7.x & 0x0000FFFFu;
ushort texIndex_normalIdx = material.indices0_3.x >> 16u;
ushort texIndex_detailNormMapIdx0 = material.indices4_7.x >> 16u;
ushort texIndex_detailNormMapIdx1 = material.indices4_7.y & 0x0000FFFFu;
ushort texIndex_detailNormMapIdx2 = material.indices4_7.y >> 16u;
ushort texIndex_detailNormMapIdx3 = material.indices4_7.z & 0x0000FFFFu;
uint objLightMask = worldMaterialIdx[inPs.drawId].z;
//Prepare weight map for the detail maps.
midf4 detailWeights = SampleDetailWeightMap( textureMaps2,
samplerState3,
UV_DETAIL_WEIGHT( inPs.uv0.xy ),
texIndex_weightMapIdx );
/// Sample detail maps and weight them against the weight map in the next foreach loop.
midf4 detailCol0 = SampleDetailCol0( textureMaps3,
samplerState3,
UV_DETAIL0( inPs.uv0.xy * material.detailOffsetScale[0].zw + material.detailOffsetScale[0].xy ),
texIndex_detailMapIdx0 );
detailWeights.x *= detailCol0.w;
detailCol0.w = detailWeights.x;
midf4 detailCol1 = SampleDetailCol1( textureMaps0,
samplerState3,
UV_DETAIL1( inPs.uv0.xy * material.detailOffsetScale[1].zw + material.detailOffsetScale[1].xy ),
texIndex_detailMapIdx1 );
detailWeights.y *= detailCol1.w;
detailCol1.w = detailWeights.y;
midf4 detailCol2 = SampleDetailCol2( textureMaps0,
samplerState3,
UV_DETAIL2( inPs.uv0.xy * material.detailOffsetScale[2].zw + material.detailOffsetScale[2].xy ),
texIndex_detailMapIdx2 );
detailWeights.z *= detailCol2.w;
detailCol2.w = detailWeights.z;
midf4 detailCol3 = SampleDetailCol3( textureMaps0,
samplerState3,
UV_DETAIL3( inPs.uv0.xy * material.detailOffsetScale[3].zw + material.detailOffsetScale[3].xy ),
texIndex_detailMapIdx3 );
detailWeights.w *= detailCol3.w;
detailCol3.w = detailWeights.w;
/// DIFFUSE MAP
pixelData.diffuse = SampleDiffuse( textureMaps0,
samplerState3,
UV_DIFFUSE( inPs.uv0.xy ),
texIndex_diffuseIdx );
/// Blend the detail diffuse maps with the main diffuse.
@insertpiece( NormalNonPremul) @add( t, 1 )
@insertpiece( NormalNonPremul) @add( t, 1 )
@insertpiece( NormalNonPremul) @add( t, 1 )
@insertpiece( NormalNonPremul) @add( t, 1 )
/// Apply the material's diffuse over the textures
pixelData.diffuse.xyz *= midf3_c( material.kD.xyz );
/// SPECUlAR MAP
pixelData.specular.xyz = midf3_c( material.kS.xyz );
pixelData.F0 = float_fresnel_c( material.F0.x );
/// ROUGHNESS MAP
pixelData.perceptualRoughness = midf_c( material.kS.w );
pixelData.roughness = max( pixelData.perceptualRoughness * pixelData.perceptualRoughness, _h( 0.001f ) );
// Geometric normal
pixelData.geomNormal = normalize( inPs.normal ) ;
//Normal mapping.
pixelData.geomNormal = normalize( inPs.normal ) ;
midf3 vTangent = normalize( inPs.tangent );
//Get the TBN matrix
midf3 vBinormal = normalize( cross( pixelData.geomNormal, vTangent ) * inPs.biNormalReflection );
midf3x3 TBN = buildMidf3x3( vTangent, vBinormal, pixelData.geomNormal );
pixelData.normal = getTSNormal( textureMaps@value( normal_map_tex_idx ),
samplerState@value( normal_map_tex_sampler ),
UV_NORMAL( inPs.uv@value(uv_normal).xy ),
texIndex_normalIdx );
// Apply the weight to the main normal map
pixelData.normal = lerp( midf3_c( 0.0, 0.0, 1.0 ), pixelData.normal, normalMapWeight );
/// If there is no normal map, the first iteration must
/// initialize pixelData.normal instead of try to merge with it.
getTSNormal( textureMaps@value(detail_map_nm0_idx),
samplerState@value(detail_map_nm0_sampler),
UV_DETAIL_NM0( inPs.uv@value(uv_detail_nm0).xy * material.detailOffsetScale[0].zw + material.detailOffsetScale[0].xy ),
texIndex_detailNormMapIdx0 ) * detailWeights.x @end
@piece( SampleDetailMapNm1 )getTSNormal( textureMaps@value(detail_map_nm1_idx),
samplerState@value(detail_map_nm1_sampler),
UV_DETAIL_NM1( inPs.uv@value(uv_detail_nm1).xy * material.detailOffsetScale[1].zw + material.detailOffsetScale[1].xy ),
texIndex_detailNormMapIdx1 ) * detailWeights.y @end
@piece( SampleDetailMapNm2 )getTSNormal( textureMaps@value(detail_map_nm2_idx),
samplerState@value(detail_map_nm2_sampler),
UV_DETAIL_NM2( inPs.uv@value(uv_detail_nm2).xy * material.detailOffsetScale[2].zw + material.detailOffsetScale[2].xy ),
texIndex_detailNormMapIdx2 ) * detailWeights.z @end
@piece( SampleDetailMapNm3 )getTSNormal( textureMaps@value(detail_map_nm3_idx),
samplerState@value(detail_map_nm3_sampler),
UV_DETAIL_NM3( inPs.uv@value(uv_detail_nm3).xy * material.detailOffsetScale[3].zw + material.detailOffsetScale[3].xy ),
texIndex_detailNormMapIdx3 ) * detailWeights.w @end
/// Blend the detail normal maps with the main normal.
float3 vDetail =
getTSDetailNormal( textureMaps[@value(detail_map_nm0_idx)], float3( inPs.uv0.xy * material.detailOffsetScale[0].zw + material.detailOffsetScale[0].xy , @value(detail_map_nm0_idx_slice) ) )
;
pixelData.normal.xy += vDetail.xy;
pixelData.normal.z *= vDetail.z + 1.0 - detailWeights.x ;
vDetail =
getTSDetailNormal( textureMaps[@value(detail_map_nm1_idx)], float3( inPs.uv0.xy * material.detailOffsetScale[1].zw + material.detailOffsetScale[1].xy , @value(detail_map_nm1_idx_slice) ) )
;
pixelData.normal.xy += vDetail.xy;
pixelData.normal.z *= vDetail.z + 1.0 - detailWeights.y ;
vDetail =
getTSDetailNormal( textureMaps[@value(detail_map_nm2_idx)], float3( inPs.uv0.xy * material.detailOffsetScale[2].zw + material.detailOffsetScale[2].xy , @value(detail_map_nm2_idx_slice) ) )
;
pixelData.normal.xy += vDetail.xy;
pixelData.normal.z *= vDetail.z + 1.0 - detailWeights.z ;
vDetail =
getTSDetailNormal( textureMaps[@value(detail_map_nm3_idx)], float3( inPs.uv0.xy * material.detailOffsetScale[3].zw + material.detailOffsetScale[3].xy , @value(detail_map_nm3_idx_slice) ) )
;
pixelData.normal.xy += vDetail.xy;
pixelData.normal.z *= vDetail.z + 1.0 - detailWeights.w ;
pixelData.normal = normalize( mul( TBN, pixelData.normal ) );
midf fShadow = _h( 1.0 );
midf fShadowBlend = _h( 1.0 );
if( inPs.depth <= passBuf.pssmSplitPoints@value(CurrentShadowMap) )
{
fShadow = getShadow( hlms_shadowmap@value(CurrentShadowMap), shadowSampler,
inPs_posL0,
passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
hlms_shadowmap@counter(CurrentShadowMap)_uv_param );
if( inPs.depth > passBuf.pssmBlendPoints@value(CurrentShadowMapBlend) )
{
fShadowBlend = getShadow( hlms_shadowmap@value(CurrentShadowMap), shadowSampler,
inPs_posL1,
passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
hlms_shadowmap@value(CurrentShadowMap)_uv_param );
fShadow = lerp(
fShadow, fShadowBlend,
midf_c( ( inPs.depth - passBuf.pssmBlendPoints@value( CurrentShadowMapBlend ) ) /
( passBuf.pssmSplitPoints@value( CurrentShadowMapBlend ) -
passBuf.pssmBlendPoints@counter( CurrentShadowMapBlend ) ) ) );
}
}
else if( inPs.depth <= passBuf.pssmSplitPoints@value(CurrentShadowMap) )
{
fShadow = getShadow( hlms_shadowmap@value(CurrentShadowMap), shadowSampler,
inPs_posL1,
passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
hlms_shadowmap@counter(CurrentShadowMap)_uv_param );
if( inPs.depth > passBuf.pssmBlendPoints@value(CurrentShadowMapBlend) )
{
fShadowBlend = getShadow( hlms_shadowmap@value(CurrentShadowMap), shadowSampler,
inPs_posL@value(CurrentShadowMap),
passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
hlms_shadowmap@value(CurrentShadowMap)_uv_param );
fShadow = lerp(
fShadow, fShadowBlend,
midf_c( ( inPs.depth - passBuf.pssmBlendPoints@value( CurrentShadowMapBlend ) ) /
( passBuf.pssmSplitPoints@value( CurrentShadowMapBlend ) -
passBuf.pssmBlendPoints@counter( CurrentShadowMapBlend ) ) ) );
}
}
else if( inPs.depth <= passBuf.pssmSplitPoints@value(CurrentShadowMap) )
{
fShadow = getShadow( hlms_shadowmap@value(CurrentShadowMap), shadowSampler,
inPs_posL2,
passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize
hlms_shadowmap@counter(CurrentShadowMap)_uv_param );
if( inPs.depth > passBuf.pssmFadePoint )
{
fShadow = lerp( fShadow, _h( 1.0 ),
midf_c( ( inPs.depth - passBuf.pssmFadePoint ) /
( passBuf.pssmSplitPoints@value( hlms_pssm_splits_minus_one ) -
passBuf.pssmFadePoint ) ) );
}
}
//Everything's in Camera space
pixelData.viewDir = midf3_c( normalize( -inPs.pos ) );
pixelData.NdotV = saturate( dot( pixelData.normal, pixelData.viewDir ) );
midf3 finalColour = midf3_c(0, 0, 0);
float3 lightDir;
float fDistance;
midf3 tmpColour;
midf spotCosAngle;
pixelData.reflDir = _h( 2.0 ) * dot( pixelData.viewDir, pixelData.normal ) * pixelData.normal -
pixelData.viewDir;
midf ambientWD =
dot( midf3_c( passBuf.ambientHemisphereDir.xyz ), pixelData.normal ) * _h( 0.5 ) + _h( 0.5 );
midf ambientWS =
dot( midf3_c( passBuf.ambientHemisphereDir.xyz ), pixelData.reflDir ) * _h( 0.5 ) + _h( 0.5 );
if( (objLightMask & light0Buf.lights[@counter(fineMaskLightIdx)].lightMask) != 0u )
finalColour += BRDF( midf3_c( light0Buf.lights[0].position.xyz ),
midf3_c( light0Buf.lights[0].diffuse.xyz ),
midf3_c( light0Buf.lights[0].specular ), pixelData PASSBUF_ARG ) * fShadow;
pixelData.envColourS = midf3_c( 0, 0, 0 );
pixelData.envColourD = midf3_c( 0, 0, 0 );
float tmpAmbientWS = ambientWD;
float tmpAmbientWD = ambientWS;
pixelData.envColourS += lerp( midf3_c( passBuf.ambientLowerHemi.xyz ),
midf3_c( passBuf.ambientUpperHemi.xyz ), tmpAmbientWS );
pixelData.envColourD += lerp( midf3_c( passBuf.ambientLowerHemi.xyz ),
midf3_c( passBuf.ambientUpperHemi.xyz ), tmpAmbientWD );
//Normally we'd use VdotH. However:
// H = normalize(lightDir + viewDir)
//since:
// lightDir = pixelData.reflDir
//then:
// H = geomNormal
//Thus H = N, and therefore we use VdotN (NdotV)
//float VdotH = saturate( dot( pixelData.viewDir, normalize( pixelData.reflDir + pixelData.viewDir ) ) );
float_fresnel fresnelS = pixelData.F0 + pow( _h( 1.0 ) - pixelData.NdotV, _h( 5.0 ) ) * (max( make_float_fresnel( _h( 1.0 ) - pixelData.perceptualRoughness ), pixelData.F0 ) - pixelData.F0);
#define brdfLUT ltcMatrix
midf3 envBRDF = OGRE_SampleArray2DF16( brdfLUT, ltcSampler,
float2( pixelData.NdotV,
1.0 - pixelData.perceptualRoughness ), 2 ).xyz;
midf fresnelD = _h( 1.0f ) - fresnelS;
midf3 Rd = pixelData.envColourD * pixelData.diffuse.xyz * _h( 3.141592654 ) * fresnelD * envBRDF.z;
midf3 Rs = pixelData.envColourS * pixelData.specular.xyz *
( fresnelS * envBRDF.x + envBRDF.y );
finalColour += Rd + Rs;
///!hlms_prepass
///!hlms_normal || hlms_qtangent
outPs_colour0.xyz = finalColour;
midf finalAlpha = _h( 1.0f );
outPs_colour0.w = finalAlpha;
return outPs;
}
Code: Select all
{
"comment" :
[
"PlanetTerra default PBS material - INITIAL TEMPLATE ONLY.",
"DatablockPbsComponent clones this on first use and stores its own per-instance data.",
"",
"Normal maps: all detail NMs must be BC5_SNORM DDS.",
"UV scale: adjust via PlanetTerraComponent AttrDetailUVScale (default 128)."
],
"samplers" :
{
"PlanetTerra_Sampler" :
{
"min" : "anisotropic",
"mag" : "anisotropic",
"mip" : "anisotropic",
"u" : "wrap",
"v" : "wrap",
"w" : "wrap",
"miplodbias" : 0,
"max_anisotropic" : 8,
"compare_function" : "disabled",
"border" : [1, 1, 1, 1],
"min_lod" : -3.40282e+38,
"max_lod" : 3.40282e+38
}
},
"macroblocks" :
{
"PlanetTerra_Macroblock" :
{
"scissor_test" : false,
"depth_check" : true,
"depth_write" : true,
"depth_function" : "less_equal",
"depth_bias_constant" : 0,
"depth_bias_slope_scale" : 0,
"cull_mode" : "clockwise",
"polygon_mode" : "solid"
}
},
"blendblocks" :
{
"PlanetTerra_Blendblock" :
{
"alpha_to_coverage" : false,
"blendmask" : "rgba",
"separate_blend" : false,
"src_blend_factor" : "one",
"dst_blend_factor" : "zero",
"blend_operation" : "add"
}
},
"pbs" :
{
"PlanetTerraDefaultMaterial" :
{
"macroblock" : "PlanetTerra_Macroblock",
"blendblock" : "PlanetTerra_Blendblock",
"shadow_const_bias" : 0.001,
"workflow" : "specular_fresnel",
"brdf" : "cook_torrance",
"roughness" : 0.85,
"fresnel" :
{
"value" : 0.02,
"mode" : "coeff"
},
"specular" :
{
"value" : [0.04, 0.04, 0.04]
},
"diffuse" :
{
"value" : [1, 1, 1],
"background" : [1, 1, 1, 1],
"texture" : "ground_dirt_gardenD.png",
"sampler" : "PlanetTerra_Sampler"
},
"normal" :
{
"comment" : "flat_normal.dds (BC5_SNORM) - required to declare textureMaps array in shader.",
"value" : 0.0,
"texture" : "ground_dirt_gardenN.dds",
"sampler" : "PlanetTerra_Sampler"
},
"detail_weight" :
{
"texture" : "PlanetTerraBlendDefault.png",
"sampler" : "PlanetTerra_Sampler"
},
"detail_diffuse0" :
{
"mode" : "NormalNonPremul",
"offset" : [0, 0],
"scale" : [128, 128],
"texture" : "adesert_cracks_d.jpg",
"sampler" : "PlanetTerra_Sampler"
},
"detail_normal0" :
{
"value" : 1.0,
"offset" : [0, 0],
"scale" : [128, 128],
"texture" : "adesert_cracks_n.dds",
"sampler" : "PlanetTerra_Sampler"
},
"detail_diffuse1" :
{
"mode" : "NormalNonPremul",
"offset" : [0, 0],
"scale" : [128, 128],
"texture" : "grass_green_d.jpg",
"sampler" : "PlanetTerra_Sampler"
},
"detail_normal1" :
{
"value" : 1.0,
"offset" : [0, 0],
"scale" : [128, 128],
"texture" : "grass_green_n.dds",
"sampler" : "PlanetTerra_Sampler"
},
"detail_diffuse2" :
{
"mode" : "NormalNonPremul",
"offset" : [0, 0],
"scale" : [128, 128],
"texture" : "island_sand_d.jpg",
"sampler" : "PlanetTerra_Sampler"
},
"detail_normal2" :
{
"value" : 1.0,
"offset" : [0, 0],
"scale" : [128, 128],
"texture" : "island_sand_n.dds",
"sampler" : "PlanetTerra_Sampler"
},
"detail_diffuse3" :
{
"mode" : "NormalNonPremul",
"offset" : [0, 0],
"scale" : [128, 128],
"texture" : "mntn_black_d.jpg",
"sampler" : "PlanetTerra_Sampler"
},
"detail_normal3" :
{
"value" : 1.0,
"offset" : [0, 0],
"scale" : [128, 128],
"texture" : "mntn_black_n.dds",
"sampler" : "PlanetTerra_Sampler"
}
}
}
}