From ce270e763862558a3bb01c42f29d53390f601cab Mon Sep 17 00:00:00 2001 From: ManuelBlanc Date: Thu, 31 Jan 2019 10:10:17 +0100 Subject: [PATCH 1/2] Remove shader libraries; add texture import config --- .../import_config/texture_format_spec.config | 37 + .../shader_libraries/common.shader_source | 2016 ----------------- .../shader_libraries/gui.shader_source | 613 ----- 3 files changed, 37 insertions(+), 2629 deletions(-) create mode 100644 vmf/core/import_config/texture_format_spec.config delete mode 100644 vmf/core/stingray_renderer/shader_libraries/common.shader_source delete mode 100644 vmf/core/stingray_renderer/shader_libraries/gui.shader_source diff --git a/vmf/core/import_config/texture_format_spec.config b/vmf/core/import_config/texture_format_spec.config new file mode 100644 index 0000000..8a09b05 --- /dev/null +++ b/vmf/core/import_config/texture_format_spec.config @@ -0,0 +1,37 @@ +formats = { + R8G8B8A8 = {compressed=false, alpha=true} + A8R8G8B8 = {compressed=false, alpha=true} + + R16G16B16A16F = {compressed=false, alpha=true} + R32G32B32A32F = {compressed=false, alpha=true, hidden=true} + + R32F = {compressed=false, alpha=true, hidden=true} + R16F = {compressed=false, alpha=true, hidden=true} + R16UNORM = {compressed=false, alpha=true, hidden=true} + R16G16F = {compressed=false, alpha=true, hidden=true} + + BC1 = {min_width=4, min_height=4, alpha=false, hidden=true} + BC2 = {min_width=4, min_height=4, alpha=false, hidden=true} + BC3 = {min_width=4, min_height=4, alpha=false, hidden=true} + BC4 = {min_width=4, min_height=4, alpha=false} + BC5 = {min_width=4, min_height=4, alpha=false} + BC7 = {min_width=4, min_height=4, alpha=true} + + DXT1 = {min_width=4, min_height=4, alpha=true} + DXT1a = {min_width=4, min_height=4, alpha=true} + DXT3 = {min_width=4, min_height=4, alpha=false} + DXT5 = {min_width=4, min_height=4, alpha=true} + DXT5n = {min_width=4, min_height=4, alpha=false} +} + +platforms = { + win32 = { + formats = [ + "R8G8B8A8", "A8R8G8B8", + "R16G16B16A16F", "R32G32B32A32F", + "R32F", "R16F", "R16UNORM", "R16G16F", + "BC1", "BC2", "BC3", "BC4", "BC5", + "DXT1", "DXT1a", "DXT3", "DXT5", "DXT5n" + ] + } +} diff --git a/vmf/core/stingray_renderer/shader_libraries/common.shader_source b/vmf/core/stingray_renderer/shader_libraries/common.shader_source deleted file mode 100644 index ffc83b7..0000000 --- a/vmf/core/stingray_renderer/shader_libraries/common.shader_source +++ /dev/null @@ -1,2016 +0,0 @@ - -render_states = { - // Stencil mask bit allocation: - // |3221 1000| - // 3 = Outline (1 = outline, 0 = no outline) - // 2 = Decal projection mask (00 = not receiving, 01 = decal_group_1, 10 = decal_group_2, 11 = decal_group3) - // 1 = Material mask (00 = default, 01 = SKIN) - // 0 = Temporary / Scratch pad (used for Cascaded Shadow Map slice cut-out) - - - default = { - states = { - defined_DOUBLE_SIDED = { - cull_mode = "cull_none" - } - ndefined_DOUBLE_SIDED = { - cull_mode = "cull_cw" - } - - z_enable = "true" - z_write_enable = "true" - z_func = "less_equal" - blend_enable = "false" - write_mask0 = "red|green|blue|alpha" - write_mask1 = "red|green|blue|alpha" - write_mask2 = "red|green|blue|alpha" - write_mask3 = "red|green|blue|alpha" - - stencil_enable = "false" - stencil_func = "always" - stencil_fail = "stencil_op_keep" - stencil_mask = "0xff" - stencil_pass = "stencil_op_keep" - stencil_ref = "0x1" - stencil_write_mask = "0xff" - stencil_z_fail = "stencil_op_keep" - - stencil_func_back_side = "always" - stencil_fail_back_side = "stencil_op_keep" - stencil_pass_back_side = "stencil_op_keep" - stencil_z_fail_back_side = "stencil_op_keep" - - defined_RENDERER_D3D11 = { - depth_bias = "0" - slope_scale_depth_bias = "0.0" - - independent_blend_enable = "false" - sample_mask = "0xffffffff" - nv_dbt_enable = "false" - multisample_antialias = "true" - - write_mask4 = "red|green|blue|alpha" - write_mask5 = "red|green|blue|alpha" - write_mask6 = "red|green|blue|alpha" - write_mask7 = "red|green|blue|alpha" - - defined_ALPHA_TO_COVERAGE = { - alpha_to_coverage_enable = "true" - } - ndefined_ALPHA_TO_COVERAGE = { - alpha_to_coverage_enable = "false" - } - srgb0 = "false" - } - defined_RENDERER_D3D12 = { - depth_bias = "0" - slope_scale_depth_bias = "0.0" - - independent_blend_enable = "false" - sample_mask = "0xffffffff" - nv_dbt_enable = "false" - multisample_antialias = "true" - - write_mask4 = "red|green|blue|alpha" - write_mask5 = "red|green|blue|alpha" - write_mask6 = "red|green|blue|alpha" - write_mask7 = "red|green|blue|alpha" - - defined_ALPHA_TO_COVERAGE = { - alpha_to_coverage_enable = "true" - } - ndefined_ALPHA_TO_COVERAGE = { - alpha_to_coverage_enable = "false" - } - srgb0 = "false" - } - - defined_RENDERER_GL = { - offset_factor = "0" - offset_units = "0" - depth_bias_enable = "false" - srgb = "false" - depth_bounds_test_enable = "false" - depth_bounds_near = "0.0" - depth_bounds_far = "0.0" - } - - defined_RENDERER_GNM = { - offset_clamp = "0" - offset_scale_front = "0" - offset_front = "0" - } - } - } - - - ambient = { - inherits = "default" - } - - gbuffer_ambient = { - inherits = "default" - } - - gbuffer_material = { - inherits = "default" - - states = { - // TODO: this does not work of some reason. - //defined_RENDERER_D3D11 = { - //defined_D3D11 = { // We need to enable this for the ps4 - stencil_enable = "true" - stencil_mask = "0x78" - stencil_write_mask = "0x78" - - stencil_func = "always" - stencil_pass = "stencil_op_replace" - stencil_fail = "stencil_op_keep" - stencil_z_fail = "stencil_op_keep" - - stencil_func_back_side = "always" - stencil_pass_back_side = "stencil_op_replace" - stencil_fail_back_side = "stencil_op_keep" - stencil_z_fail_back_side = "stencil_op_keep" - - // Observation: If we had a way to do sequenctial bit manipulation of state values this would be soo much cleaner, easier and more powerful! - defined_DEFERRED_DECALS_GROUP_1 = { - defined_SKIN = { - stencil_ref = "0x28" - } - ndefined_SKIN = { - stencil_ref = "0x20" - } - } - ndefined_DEFERRED_DECALS_GROUP_1 = { - defined_DEFERRED_DECALS_GROUP_2 = { - defined_SKIN = { - stencil_ref = "0x48" - } - ndefined_SKIN = { - stencil_ref = "0x40" - } - } - ndefined_DEFERRED_DECALS_GROUP_2 = { - defined_DEFERRED_DECALS_GROUP_3 = { - defined_SKIN = { - stencil_ref = "0x68" - } - ndefined_SKIN = { - stencil_ref = "0x60" - } - } - ndefined_DEFERRED_DECALS_GROUP_3 = { - defined_SKIN = { - stencil_ref = "0x8" - } - ndefined_SKIN = { - stencil_ref = "0x0" - } - } - } - } - //} - } - } - - depth_only = { - inherits = "default" - states = { - write_mask0 = "0x0" - write_mask1 = "0x0" - write_mask2 = "0x0" - write_mask3 = "0x0" - } - } - - shadow_caster = { - inherits = "depth_only" - states = { - defined_RENDERER_D3D11 = { - depth_bias = "0xff" - slope_scale_depth_bias = "2.5" - } - defined_RENDERER_D3D12 = { - depth_bias = "0xff" - slope_scale_depth_bias = "2.5" - } - defined_RENDERER_GL = { - offset_factor = "1.1" - offset_units = "4.0" - depth_bias_enable = "true" - } - defined_RENDERER_GNM = { - offset_clamp = "0.01" - offset_scale_front = "16.0" - offset_front = "0.0001" - offset_z_format = "z_format_32" - } - } - } - - opacity = { - inherits = "default" - states = { - z_write_enable = "false" - cull_mode = "cull_none" - blend_enable = "true" - blend_op = "blend_op_add" - dest_blend = "blend_inv_src_alpha" - src_blend = "blend_src_alpha" - } - } - - opacity_add = { - inherits = "opacity" - states = { - dest_blend = "blend_one" - src_blend = "blend_src_alpha" - } - } - - opacity_mul = { - inherits = "opacity" - states = { - dest_blend = "blend_one" - src_blend = "blend_dest_color" - } - } -} - -sampler_states = { - wrap_anisotropic = { - states = { - address_u = "address_wrap" - address_v = "address_wrap" - ndefined_RENDERER_GL = { - filter = "anisotropic" - max_anisotropy = "4" - } - defined_RENDERER_GL = { - max_anisotropy = "2.0" - filter = "min_mag_linear_mip_point" - } - - srgb = "false" - } - } - - wrap_linear = { - states = { - address_u = "address_wrap" - address_v = "address_wrap" - defined_RENDERER_GL = { - filter = "min_mag_linear_mip_point" - } - ndefined_RENDERER_GL = { - filter = "min_mag_mip_linear" - } - srgb = "false" - } - } - - wrap_point = { - states = { - address_u = "address_wrap" - address_v = "address_wrap" - filter = "min_mag_mip_point" - srgb = "false" - } - } - - wrap_anisotropic_srgb = { - inherits = "wrap_anisotropic" - states = { - srgb = "true" - } - } - - wrap_linear_srgb = { - inherits = "wrap_linear" - states = { - srgb = "true" - } - } - - wrap_point_srgb = { - inherits="wrap_point" - states = { - srgb = "true" - } - } - - clamp = { - states = { - srgb = "false" - defined_RENDERER_GL = { - address_u = "address_clamp_to_edge" - address_v = "address_clamp_to_edge" - address_w = "address_clamp_to_edge" - } - defined_RENDERER_D3D11 = { - address_u = "address_clamp" - address_v = "address_clamp" - address_w = "address_clamp" - } - defined_RENDERER_D3D12 = { - address_u = "address_clamp" - address_v = "address_clamp" - address_w = "address_clamp" - } - defined_RENDERER_GNM = { - address_u = "address_clamp" - address_v = "address_clamp" - address_w = "address_clamp" - } - } - } - - clamp_point = { - inherits="clamp" - states = { - filter = "min_mag_mip_point" - } - } - - clamp_linear = { - inherits="clamp" - states = { - defined_RENDERER_GL = { - filter = "min_mag_linear_mip_point" - } - ndefined_RENDERER_GL = { - filter = "min_mag_mip_linear" - } - } - } - - clamp_point_srgb = { - inherits = "clamp_point" - states = { - srgb = "true" - } - } - - clamp_linear_srgb = { - inherits = "clamp_linear" - states = { - srgb = "true" - } - } - - clamp_anisotropic_srgb = { - inherits = "clamp" - states = { - srgb = "true" - ndefined_RENDERER_GL = { - filter = "anisotropic" - max_anisotropy = "4" - } - defined_RENDERER_GL = { - max_anisotropy = "2.0" - filter = "min_mag_linear_mip_point" - } - } - } - - clamp_anisotropic = { - inherits = "clamp_anisotropic_srgb" - states = { - srgb = "false" - } - } -} - -hlsl_shaders = { - common = { - // Compatibility stuff for old library compiler - vp_code = { ref = "code" } - ep_code = { ref = "code" } - cp_code = { ref = "code" } - gp_code = { ref = "code" } - fp_code = { ref = "code" } - - code = """ - #if defined(RENDERER_GL) - #define new_fixed(x) float((x)) - #define new_fixed2(x, y) vec2((x), (y)) - - #define new_fixed3_xy(xy, z) vec3((xy), (z)) - #define new_fixed3(x, y, z) vec3((x), (y), (z)) - - #define new_fixed4_xyz(xyz, w) vec4((xyz), (w)) - #define new_fixed4_xy(xy, z, w) vec4((xy), (z), (w)) - #define new_fixed4(x, y, z, w) vec4((x), (y), (z), (w)) - - #define new_half(x) float((x)) - #define new_half2(x, y) vec2((x), (y)) - - #define new_half3_xy(xy, z) vec3((xy), (z)) - #define new_half3(x, y, z) vec3((x), (y), (z)) - #define new_half3_xyz(xyz) vec3((xyz)) - - #define new_half4_xyz(xyz, w) vec4((xyz), (w)) - #define new_half4_xy(xy, z, w) vec4((xy), (z), (w)) - #define new_half4(x, y, z, w) vec4((x), (y), (z), (w)) - - #define new_float(x) float((x)) - #define new_float2(x, y) vec2((x), (y)) - - #define new_float3_xy(xy, z) vec3((xy), (z)) - #define new_float3(x, y, z) vec3((x), (y), (z)) - - #define new_float4_xyz(xyz, w) vec4((xyz), (w)) - #define new_float4_xy(xy, z, w) vec4((xy), (z), (w)) - #define new_float4(x, y, z, w) vec4((x), (y), (z), (w)) - #else - #define new_fixed half - #define new_fixed2 fixed2 - #define new_fixed3 fixed3 - #define new_fixed3_xy fixed3 - #define new_fixed4 fixed4 - #define new_fixed4_xy fixed4 - #define new_fixed4_xyz fixed4 - - #define new_half half - #define new_half2 half2 - #define new_half3 float3 - #define new_half3_xy float3 - #define new_half3_xyz float3 - #define new_half4 half4 - #define new_half4_xy half4 - #define new_half4_xyz half4 - - #define new_float float - #define new_float2 float2 - #define new_float3 float3 - #define new_float3_xy float3 - #define new_float4 float4 - #define new_float4_xy float4 - #define new_float4_xyz float4 - - #define equal(a,b) (a)==(b) - #define lessThan(a,b) (a)<(b) - #define lessThanEqual(a,b) (a)<=(b) - #define greaterThan(a,b) (a)>(b) - #define greaterThanEqual(a,b) (a)>=(b) - #define notEqual(a,b) (a)!=(b) - #endif - - #if defined(RENDERER_D3D11) || defined(RENDERER_D3D12) - #define CBUFFER_START(name) cbuffer name { - #define CBUFFER_END }; - #define DX10_STYLE_SAMPLERS - #define NO_INTERPOLATION nointerpolation - - #elif defined(RENDERER_GNM) - #pragma warning(disable: 5609) // On ps4, halfs are treated as floats. Let's disable the warning. - #pragma warning(disable: 5203) // Todo: Remove this warning when GAME-6418 is closed. - - #pragma warning(disable: 5202) - #pragma warning(disable: 5206) - #pragma warning(disable: 6002) - - #define CBUFFER_START(name) ConstantBuffer name { - #define CBUFFER_END }; - #define SV_TARGET0 S_TARGET_OUTPUT0 - #define SV_TARGET1 S_TARGET_OUTPUT1 - #define SV_TARGET2 S_TARGET_OUTPUT2 - #define SV_TARGET3 S_TARGET_OUTPUT3 - #define SV_POSITION S_POSITION - #define SV_DEPTH S_DEPTH_OUTPUT - - #define Buffer DataBuffer - #define SV_InstanceId S_INSTANCE_ID - - #define reversebits ReverseBits - #define DX10_STYLE_SAMPLERS - - #define SV_TessFactor S_EDGE_TESS_FACTOR - #define SV_InsideTessFactor S_INSIDE_TESS_FACTOR - #define SV_OutputControlPointID S_OUTPUT_CONTROL_POINT_ID - #define SV_DomainLocation S_DOMAIN_LOCATION - #define domain DOMAIN_PATCH_TYPE - #define partitioning PARTITIONING_TYPE - #define outputtopology OUTPUT_TOPOLOGY_TYPE - #define outputcontrolpoints OUTPUT_CONTROL_POINTS - #define patchconstantfunc PATCH_CONSTANT_FUNC - #define maxtessfactor MAX_TESS_FACTOR - #if defined(STAGE_VERTEX) - #define WORLDPOS S_POSITION - #else - #define WORLDPOS POSITION - #endif - #define SV_PrimitiveID S_PRIMITIVE_ID - #define NO_INTERPOLATION nointerp - - #elif defined(RENDERER_GL) - // Default to highp to imitate hlsl closer - precision highp float; - precision highp int; - precision highp usampler2D; - - #define PRECISION precision - #define LOWP lowp - #define MEDIUMP mediump - #define HIGHP highp - - #define inline - #define static - #define half mediump float - #define half2 mediump vec2 - #define float3 mediump vec3 - #define half4 mediump vec4 - - #define fixed lowp float - #define fixed2 lowp vec2 - #define fixed3 lowp vec3 - #define fixed4 lowp vec4 - - #define float2 vec2 - #define float3 vec3 - #define float4 vec4 - - #define int2 ivec2 - #define int3 ivec3 - #define int4 ivec4 - - #define uint2 uvec2 - #define uint3 uvec3 - #define uint4 uvec4 - - #define float2x2 mat2 - #define float3x3 mat3 - #define float4x4 mat4 - - #define mul(a, b) ((a) * (b)) - #define frac(a) fract(a) - #define lerp(a, b, c) mix(a, b, c) - #define modf mod - - // fmod() != mod() for negative numbers - // % works on float for HLSL, but GLSL requires integral - #define fmod(a, b) (a - b * trunc(a/b)) - - #define ddx dFdx - #define ddy dFdy - #define rsqrt inversesqrt - - float saturate(float v) { return clamp(v, 0.f, 1.f); } - vec2 saturate(vec2 v) { return clamp(v, vec2(0.f), vec2(1.f)); } - vec3 saturate(vec3 v) { return clamp(v, vec3(0.f), vec3(1.f)); } - vec4 saturate(vec4 v) { return clamp(v, vec4(0.f), vec4(1.f)); } - - #define CBUFFER_START(name)// uniform name { - #define CBUFFER_END// }; - - // Attribute mappings taken from the GL backend. - // {0, 15, -1, -1, -1, -1, -1, -1, -1, -1}, // POSITION - // {1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // NORMAL - // {2, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // TANGENT - // {3, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // BINORMAL - // {8, 9, 10, 11, 12, 13, 6, 7, 14, 15}, // TEXCOORD - // {4, 5, 6, 7, -1, -1, -1, -1, -1, -1}, // COLOR - // {15, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // BLENDINDICES - // {14, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // BLENDWEIGHTS - - #define POSITION0 0 - #define POSITION1 15 - - #define NORMAL 1 - #define TANGENT 2 - #define BINORMAL 3 - - #define TEXCOORD0 8 - #define TEXCOORD1 9 - #define TEXCOORD2 10 - #define TEXCOORD3 11 - #define TEXCOORD4 12 - #define TEXCOORD5 13 - #define TEXCOORD6 6 - #define TEXCOORD7 7 - #define TEXCOORD8 14 - #define TEXCOORD9 15 - - #define COLOR0 4 - #define COLOR1 5 - #define COLOR2 6 - #define COLOR3 7 - - #define BLENDINDICES 15 - #define BLENDWEIGHTS 14 - #endif - - #if defined(RENDERER_D3D12) - - #define RS1 "RootFlags (ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), " \ - "CBV(b0, visibility = SHADER_VISIBILITY_VERTEX), " \ - "CBV(b1, visibility = SHADER_VISIBILITY_VERTEX), " \ - "CBV(b0, visibility = SHADER_VISIBILITY_PIXEL), " \ - "CBV(b1, visibility = SHADER_VISIBILITY_PIXEL), " \ - "DescriptorTable( CBV(b2, numDescriptors = 6), visibility = SHADER_VISIBILITY_VERTEX), " \ - "DescriptorTable( CBV(b2, numDescriptors = 6), visibility = SHADER_VISIBILITY_PIXEL), " \ - "DescriptorTable( SRV(t0, numDescriptors = 24), visibility = SHADER_VISIBILITY_VERTEX), " \ - "DescriptorTable( SRV(t0, numDescriptors = 24), visibility = SHADER_VISIBILITY_PIXEL), " \ - "DescriptorTable( Sampler(s0, numDescriptors = 24), visibility = SHADER_VISIBILITY_VERTEX), " \ - "DescriptorTable( Sampler(s0, numDescriptors = 24), visibility = SHADER_VISIBILITY_PIXEL) " - - - #define ROOT_SIGNATURE_ATTRIBUTE(root_signature) [RootSignature(root_signature)] - #define DEFAULT_ROOT_SIGNATURE_ATTRIBUTE ROOT_SIGNATURE_ATTRIBUTE(RS1) - #else - #define ROOT_SIGNATURE_ATTRIBUTE(root_signature) - #define DEFAULT_ROOT_SIGNATURE_ATTRIBUTE - #endif - - - #if defined(RENDERER_GL) - #define DECLARE_SAMPLER_2D(name) uniform sampler2D name - #define Sampler2D sampler2D - #define TEX2D texture - #define TEX2DLOD textureLod - - #define DECLARE_SAMPLER_CUBE(name) uniform samplerCube name - #define SamplerCube samplerCube - #define TEXCUBE texture - #define TEXCUBELOD textureLod - - #define DECLARE_SAMPLER_3D(name) uniform sampler3D name - #define Sampler3D sampler3D - #define TEX3D texture - #define TEX3DLOD textureLod - - #define DECLARE_COMPARISON_SAMPLER_2D(name) uniform highp sampler2DShadow name - #define ComparisonSampler2D highp sampler2DShadow - #define TEX2DCMP texture - #define TEX2DCMPLOD0 textureLod - - #define DECLARE_COMPARISON_SAMPLER_CUBE(name) uniform highp samplerCubeShadow name - #define ComparisonSamplerCube highp samplerCubeShadow - #define TEXCUBECMP texture - #define TEXCUBECMPLOD0 textureLod - #elif defined(DX10_STYLE_SAMPLERS) - #define CONCAT_(prefix, name) prefix ## name - #define CONCAT(prefix, name) CONCAT_(prefix, name) - #define TEXTURE_NAME(name) CONCAT(TEXTURE_PREFIX, name) - #define SAMPLER_NAME(name) CONCAT(SAMPLER_PREFIX, name) - - struct Sampler2D { Texture2D tex; SamplerState state; }; - - #define TEX2D(s, uv) s.tex.Sample(s.state, uv) - #if defined(GNM) - #define TEX2DLOD(s, uv, lod) s.tex.SampleLOD(s.state, uv, lod) - #else - #define TEX2DLOD(s, uv, lod) s.tex.SampleLevel(s.state, uv, lod) - #endif - - #define DECLARE_SAMPLER_2D(name) \ - Texture2D TEXTURE_NAME(name); \ - SamplerState SAMPLER_NAME(name); \ - static Sampler2D name = { TEXTURE_NAME(name), SAMPLER_NAME(name) }; - - #define DECLARE_SAMPLER_2D_SHARED(name, share_from) \ - Texture2D TEXTURE_NAME(name); \ - static Sampler2D name = { TEXTURE_NAME(name), SAMPLER_NAME(share_from) }; - - - - struct SamplerCube { TextureCube tex; SamplerState state; }; - - #define TEXCUBE(s, uv) s.tex.Sample(s.state, uv) - #if defined(GNM) - #define TEXCUBELOD(s, uv, lod) s.tex.SampleLOD(s.state, uv, lod) - #else - #define TEXCUBELOD(s, uv, lod) s.tex.SampleLevel(s.state, uv, lod) - #endif - - #define DECLARE_SAMPLER_CUBE(name) \ - TextureCube TEXTURE_NAME(name); \ - SamplerState SAMPLER_NAME(name); \ - static SamplerCube name = { TEXTURE_NAME(name), SAMPLER_NAME(name) }; - - #define DECLARE_SAMPLER_CUBE_SHARED(name, share_from) \ - TextureCube TEXTURE_NAME(name); \ - static SamplerCube name = { TEXTURE_NAME(name), SAMPLER_NAME(share_from) }; - - - struct Sampler3D { Texture3D tex; SamplerState state; }; - - #define TEX3D(s, uv) s.tex.Sample(s.state, uv) - #if defined(GNM) - #define TEX3DLOD(s, uv, lod) s.tex.SampleLOD(s.state, uv, lod) - #else - #define TEX3DLOD(s, uv, lod) s.tex.SampleLevel(s.state, uv, lod) - #endif - - #define DECLARE_SAMPLER_3D(name) \ - Texture3D TEXTURE_NAME(name); \ - SamplerState SAMPLER_NAME(name); \ - static Sampler3D name = { TEXTURE_NAME(name), SAMPLER_NAME(name) }; - - #define DECLARE_SAMPLER_3D_SHARED(name, share_from) \ - Texture3D TEXTURE_NAME(name); \ - static Sampler3D name = { TEXTURE_NAME(name), SAMPLER_NAME(share_from) }; - - - struct ComparisonSampler2D { Texture2D tex; SamplerComparisonState state; }; - - #define TEX2DCMP(s, uv, cmp_value) s.tex.SampleCmp(s.state, uv, cmp_value) - #if defined(GNM) - #define TEX2DCMPLOD0(s, uv, cmp_value) s.tex.SampleCmpLOD0(s.state, uv, cmp_value) - #else - #define TEX2DCMPLOD0(s, uv, cmp_value) s.tex.SampleCmpLevelZero(s.state, uv, cmp_value) - #endif - - #define DECLARE_COMPARISON_SAMPLER_2D(name) \ - Texture2D TEXTURE_NAME(name); \ - SamplerComparisonState SAMPLER_NAME(name); \ - static ComparisonSampler2D name = { TEXTURE_NAME(name), SAMPLER_NAME(name) }; - - #define DECLARE_COMPARISON_SAMPLER_2D_SHARED(name, share_from) \ - Texture2D TEXTURE_NAME(name); \ - static ComparisonSampler2D name = { TEXTURE_NAME(name), SAMPLER_NAME(share_from) }; - - struct ComparisonSamplerCube { TextureCube tex; SamplerComparisonState state; }; - - #define TEXCUBECMP(s, uv, cmp_value) s.tex.SampleCmp(s.state, uv, cmp_value) - #if defined(GNM) - #define TEXCUBECMPLOD0(s, uv, cmp_value) s.tex.SampleCmpLOD0(s.state, uv, cmp_value) - #else - #define TEXCUBECMPLOD0(s, uv, cmp_value) s.tex.SampleCmpLevelZero(s.state, uv, cmp_value) - #endif - - #define DECLARE_COMPARISON_SAMPLER_CUBE(name) \ - TextureCube TEXTURE_NAME(name); \ - SamplerComparisonState SAMPLER_NAME(name); \ - static ComparisonSamplerCube name = { TEXTURE_NAME(name), SAMPLER_NAME(name) }; - - inline float4 Sample(Sampler2D s, float2 uv, int2 offset) - { - return s.tex.Sample(s.state, uv, offset); - } - - inline float4 Sample(Sampler3D s, float3 uvw, int3 offset) - { - return s.tex.Sample(s.state, uvw, offset); - } - - inline float4 Sample(Sampler2D s, float2 uv) - { - return s.tex.Sample(s.state, uv); - } - - inline float4 Sample(Sampler3D s, float3 uvw) - { - return s.tex.Sample(s.state, uvw); - } - #else - #define DECLARE_SAMPLER_2D(name) sampler2D name; - #define Sampler2D sampler2D - #define TEX2D tex2D - #define TEX2DLOD(s, uv, lod) tex2Dlod(s, float4(uv, 0, lod)) - - #define DECLARE_SAMPLER_CUBE(name) samplerCUBE name; - #define SamplerCube samplerCUBE - #define TEXCUBELOD(s, uv, lod) texCUBElod(s, float4(uv, lod)) - #define TEXCUBE(s, uv) texCUBE(s, uv) - - #define DECLARE_SAMPLER_3D(name) sampler3D name; - #define Sampler3D sampler3D - #define TEX3D(s, uv) tex3D(s, uv) - #define TEX3DLOD(s, uv, lod) tex3Dlod(s, float4(uv, lod)) - #endif - - #if defined(RENDERER_GL) - #define UNIFORM uniform - #else - #define UNIFORM - #endif - - #define MAX_RIMLIGHT_EXPONENT 8.0 - #define MAX_GLOSSINESS 500.0 - #define ONE_BIT_ALPHA_REF 0.5 - #define PI 3.14159265358979323846 - - inline float3x3 to_mat3(float4x4 m) - { - #if defined(RENDERER_GL) - return mat3(m); - #else - return (float3x3)m; - #endif - } - - #if defined(RENDERER_D3D11) || defined(RENDERER_D3D12) || defined(RENDERER_GNM) || (defined(RENDERER_GL) && defined(STAGE_FRAGMENT)) - inline void one_bit_alpha_mask(float alpha, float ref) { - if (alpha < ref) - discard; - } - #endif - - #if defined(RENDERER_GNM) - inline bool front_facing(bool vface) { - return vface; - } - #else - inline bool front_facing(float vface) { - return vface > 0.0; - } - #endif - - //remap color to RGBA using swizzling - inline float4 decode_vertex_color(float4 col) { - #if defined(RENDERER_D3D11) || defined(RENDERER_D3D12) || defined(RENDERER_GNM) || defined(RENDERER_GL) - return col.bgra; - #else - return col; - #endif - } - - inline float3 decode_signed_normal(float3 v) { - return 2.0*(v - 0.5); - } - - inline float3 encode_signed_normal(float3 v) { - return v*0.5 + 0.5; - } - - inline float3 decode_normal_map(half4 v) { - half4 temp = 2.0*(v - 0.5); - return new_half3(temp.x, temp.y, sqrt(max(1.0 - dot(temp.xy, temp.xy), 0.0))); - } - - inline half2 decode_normal_grad(half4 v) { - half4 temp = 2.0*(v - 0.5); - #if defined(RENDERER_GNM) - return half2(temp.w, temp.y); - #else - return new_half2(temp.x, temp.y); - #endif - } - - inline half4 rgbm_encode(float3 color) { - half4 rgbm; - color = new_half3_xyz(sqrt(color)); - color *= new_half(1.0 / 6.0); - rgbm.a = clamp(max(max(color.r, color.g ), color.b), 0.0, 1.0); - rgbm.a = new_half(ceil(rgbm.a * 255.0) / 255.0); - rgbm.rgb = color / rgbm.a; - return rgbm; - } - - inline float3 rgbm_decode(half4 rgbm) { - float3 c = 6.0 * rgbm.rgb * rgbm.a; - return c * c; - } - - inline void tspace_transform_transpose(out float3 tangent_out, out float3 binormal_out, out float3 normal_out, in float3 tangent, in float3 binormal, in float3 normal, float3x3 mat) { - float3 t = normalize(mul(tangent, mat)); - float3 b = normalize(mul(binormal, mat)); - float3 n = normalize(mul(normal, mat)); - - // find transpose of 3x3matrix - tangent_out.x = t.x; tangent_out.y = b.x; tangent_out.z = n.x; - binormal_out.x = t.y; binormal_out.y = b.y; binormal_out.z = n.y; - normal_out.x = t.z; normal_out.y = b.z; normal_out.z = n.z; - } - - inline void tspace_transform(out float3 tangent_out, out float3 binormal_out, out float3 normal_out, in float3 tangent, in float3 binormal, in float3 normal, float3x3 mat) { - tangent_out = normalize(mul(tangent, mat)); - binormal_out = normalize(mul(binormal, mat)); - normal_out = normalize(mul(normal, mat)); - } - - inline void tspace_transpose(out float3 tsm0, out float3 tsm1, out float3 tsm2, in float3 t, in float3 b, in float3 n) { - tsm0 = float3(t.x, b.x, n.x); - tsm1 = float3(t.y, b.y, n.y); - tsm2 = float3(t.z, b.z, n.z); - } - - // half and float types are considered the same on gl and gnm platforms. - #if !(defined(RENDERER_GL) || defined(RENDERER_GNM)) - inline half3 rotate_vector3(half3 v, half3 x, half3 y, half3 z) { - return new_half3_xyz(normalize(half3(dot(v, x), dot(v, y), dot(v, z)))); - } - #endif - - inline float3 rotate_vector3(float3 v, float3 x, float3 y, float3 z) { - return normalize(new_float3(dot(v, x), dot(v, y), dot(v, z))); - } - - inline float3 rotate_point3(float3 v, float3 x, float3 y, float3 z) { - return new_float3(dot(v, x), dot(v, y), dot(v, z)); - } - - inline float3 fast_gamma_to_linear_rgb(float3 c) { - return c * c; - } - - inline float4 fast_gamma_to_linear_rgb(float4 c) { - return new_float4_xyz(c.rgb * c.rgb, c.a); - } - - inline float4 fast_gamma_to_linear_rgba(float4 c) { - return c * c; - } - - inline float3 fast_linear_to_gamma_rgb(float3 c) { - return sqrt(c); - } - - inline float4 fast_linear_to_gamma_rgb(float4 c) { - return new_float4_xyz(sqrt(c.rgb), c.a); - } - - inline float4 fast_linear_to_gamma_rgba(float4 c) { - return sqrt(c); - } - - CBUFFER_START(global_viewport) - UNIFORM float3 camera_unprojection; // Deprecated uniform - UNIFORM float3 camera_pos; - UNIFORM float4x4 camera_view; - UNIFORM float4x4 camera_projection; - UNIFORM float4x4 camera_inv_view; - UNIFORM float4x4 camera_inv_projection; - UNIFORM float4x4 camera_world; - UNIFORM float4x4 camera_last_world; - UNIFORM float4x4 camera_last_view; - UNIFORM float4x4 camera_last_view_projection; - UNIFORM float4x4 camera_custom_fov_view_projection; // TODO: Add a define in engine to only set this if we need it - UNIFORM float4x4 camera_custom_fov_last_view_projection; // TODO: Add a define in engine to only set this if we need it - UNIFORM float time; - UNIFORM float delta_time; - UNIFORM float frame_number; - UNIFORM float2 back_buffer_size; - UNIFORM float taa_enabled; - UNIFORM float debug_rendering; - UNIFORM float gamma; - // Screen space coordinate calculation - // X = (X + 1) * Viewport.Width * 0.5 + Viewport.TopLeftX - // Y = (1 - Y) * Viewport.Height * 0.5 + Viewport.TopLeftY - // Z = Viewport.MinDepth + Z * (Viewport.MaxDepth - Viewport.MinDepth) - // X, Y clip space coordinate range [-1, 1] =>transforms to screen space coordinate [0, 1920] and [0, 1080]. - UNIFORM float4 viewport; // width, height, top.x, top.y - #if defined(D3D11) - float capture_cubemap; - #endif - //float g_particle_lighting; - float sun_shadows; - float skin_material_enabled; - CBUFFER_END - - // will soon merge with global_viewport.. - CBUFFER_START(global_camera) - UNIFORM float3 camera_near_far; - CBUFFER_END - - CBUFFER_START(c_environment_settings) - #if defined(HAS_SUN_DIRECTION) - UNIFORM float3 sun_direction; - #endif - #if defined(HAS_SUN_COLOR) - UNIFORM float3 sun_color; - #endif - CBUFFER_END - """ - } - - gbuffer_access = { - // Compatibility stuff for old library compiler - fp_code = { ref = "code" } - vp_code = { ref = "code" } - - code = """ - // Materials - inline float2 encode_float_rg(float v) { - float2 enc = new_float2(1.0, 255.0) * v; - enc = frac(enc); - enc -= enc.y * new_float2(1.0/255.0, 1.0/255.0); - return enc; - } - - inline float decode_float_rg(float2 rg) { - return dot(rg, new_float2(1.0, 1.0/255.0)); - } - - inline float4 encode_float_rgba(float v) { - float4 enc = new_float4(1.0, 255.0, 65025.0, 160581375.0) * v; - enc = frac(enc); - enc -= enc.yzww * new_float4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0); - return enc; - } - - inline float decode_float_rgba(float4 rgba) { - return dot(rgba, new_float4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/160581375.0)); - } - - #define DEFAULT_MATERIAL 0 - #define CLOTH_MATERIAL 1.0/255.0 - #define SKIN_MATERIAL 2.0/255.0 - #define COLORED_SPECULAR_MATERIAL 3.0/255.0 - - #if defined(RENDERER_GL) && defined(STAGE_FRAGMENT) - #define GBUFFER_OUTPUT \ - layout(location = 0) out mediump vec4 out_gbuffer0; \ - layout(location = 1) out mediump vec4 out_gbuffer1; \ - layout(location = 2) out mediump vec4 out_gbuffer2; \ - layout(location = 3) out mediump vec4 out_gbuffer3 - - #define out_base_color out_gbuffer0.rgb - #define out_metallic out_gbuffer0.a - #define out_normal out_gbuffer1.rgb - #define out_roughness out_gbuffer1.a - #define out_velocity out_gbuffer2.ba - #define out_ambient_diffuse_light out_gbuffer3 - #define out_ambient_occlusion out_gbuffer2.r - #define out_density out_gbuffer2.g - #elif !defined(RENDERER_GL) - struct GBUFFER_OUT { - half4 buffer0 : SV_TARGET0; - half4 buffer1 : SV_TARGET1; - half2 buffer2 : SV_TARGET2; - // half4 buffer3 : SV_TARGET3; // Since we don't have baked lighting, we don't use this - half2 buffer4 : SV_TARGET3; - }; - #define BASE_COLOR(gbuffer) gbuffer.buffer0.rgb - #define METALLIC(gbuffer) gbuffer.buffer0.a - #define NORMAL(gbuffer) gbuffer.buffer1.rgb - #define ROUGHNESS(gbuffer) gbuffer.buffer1.a - // #define AMBIENT_DIFFUSE_LIGHT(gbuffer) gbuffer.buffer3.rgba - #define VELOCITY(gbuffer) gbuffer.buffer4.rg - #define AMBIENT_OCCLUSION(gbuffer) gbuffer.buffer2.r - #define DENSITY(gbuffer) gbuffer.buffer2.g - #endif - - #if defined(RENDERER_D3D12) - inline float3 gbuffer_encode_base_color(float3 color) { return color; } - inline float3 gbuffer_decode_base_color(half4 c) { return c.rgb; } - #else - inline float3 gbuffer_encode_base_color(float3 color) { return new_half3_xyz(sqrt(color.xyz)); } - inline float3 gbuffer_decode_base_color(half4 c) { return c.rgb * c.rgb; } - #endif - - inline float3 gbuffer_encode_normal_hiquality(float3 normal, Sampler2D nft) { - normal = new_half3_xyz(normalize(normal)); - float3 abs_normal = abs(normal); - half max_abs_normal = max(abs_normal.x, max(abs_normal.y, abs_normal.z)); - float2 tcoord = abs_normal.z < max_abs_normal ? (abs_normal.y < max_abs_normal ? abs_normal.yz : abs_normal.xz) : abs_normal.xy; - tcoord = tcoord.x < tcoord.y ? tcoord.yx : tcoord.xy; - tcoord.y /= tcoord.x; - normal /= max_abs_normal; - half fitting_scale = new_half(TEX2D(nft, tcoord).a); - normal *= fitting_scale; - return encode_signed_normal(normal); - } - - inline float3 gbuffer_encode_normal(float3 normal) { return encode_signed_normal(normal); } - inline float3 gbuffer_decode_normal(half4 c) { return decode_signed_normal(c.rgb); } - inline half gbuffer_encode_metallic_mask(half s) { return s; } - inline half gbuffer_decode_metallic_mask(half4 c) { return saturate(c.a); } - inline half gbuffer_encode_roughness(half c) { return c; } - inline half gbuffer_decode_roughness(half4 c) { return saturate(c.a); } - inline half4 gbuffer_encode_ambient_diffuse_light(float3 col) { return rgbm_encode(new_half3_xyz(col)); } - inline float3 gbuffer_decode_ambient_diffuse_light(half4 c) { return rgbm_decode(c); } - inline half gbuffer_encode_ambient_occlusion(half c) { return c; } - inline half gbuffer_decode_ambient_occlusion(half4 c) { return saturate(c.r); } - inline half gbuffer_encode_density(half c) { return c; } - inline half gbuffer_decode_density(half4 c) { return saturate(c.g); } - - inline float linearize_depth(float clip_depth) { - return (camera_near_far.y*camera_near_far.x)/(camera_near_far.y - clip_depth*(camera_near_far.y-camera_near_far.x)); - } - - // SCALE_VELOCITY represents the maximum component size of a motion vector (in pixels). - #define SCALE_VELOCITY 50.0 - #define HALF_ONE 127.0/255.0 - inline float2 encode_velocity(float2 v) { - // On high-end platforms we don't encode velocity vectors (stored as 16F precision) - #if defined(RENDERER_D3D11) || defined(RENDERER_D3D12) || defined(RENDERER_GNM) - return v; - #else - v *= back_buffer_size/(SCALE_VELOCITY * 2.0); - return clamp(v * 0.5 + HALF_ONE, 1.0/255.0, 1.0); - #endif - } - - inline float2 decode_velocity(float2 v) { - // On high-end platforms we don't encode velocity vectors (stored as 16F precision) - #if defined(RENDERER_D3D11) || defined(RENDERER_D3D12) || defined(RENDERER_GNM) - return v; - #else - v = 2.0 * (v - HALF_ONE); - return v / (back_buffer_size / (SCALE_VELOCITY * 2.0)); - #endif - } - - #if defined(RENDERER_GL) - float gbuffer_decode_depth(uvec4 d) { - return uintBitsToFloat(d.r); - } - #else - inline float gbuffer_decode_depth(float4 c) { - return c.r; - } - #endif - - inline float4 encode_world_pos(float4 p) { - return new_float4_xyz(mul(mul(p,camera_inv_projection).xyz,to_mat3(camera_inv_view)),p.w); - } - - // Function is deprecated. Use encode_world_pos(float4) instead. - inline float4 encode_world_pos(float4 p, float3 unprojection) { - return encode_world_pos(p); - } - - inline float3 decode_world_pos(float4 p, float depth) { - return (p.xyz / p.w) * depth + camera_pos; - } - """ - } - - space_conversion = { - - // Compatibility stuff for old library compiler - fp_code = { ref = "code" } - vp_code = { ref = "code" } - - // Normalized Display Coordinates (variable prefix "ndc_") - // (1,1) - // .-----------. (Z=1) - // | | / - // | 0 | / - // | | / - // .-----------.(Z=0) - // (-1,-1) - - // Screen Space Coordinates (variable prefix "ss_") - // (1,0) - // 0-----------. (Z=1) - // | | / - // | | / - // | | / - // .-----------.(Z=0) - // (0,1) - - // View Space Coordinates (variable prefix "view_") - // (+,+) - // .-----------. (Z=Far Plane) - // | | / - // | 0 | / - // | | / - // .-----------.(Z=Near Plane) - // (-,-) - - // World Space Coordinates (variable prefix "world_") - // - // (Z+) (Y+) - // | / - // | / - // |/ - // -------0------(X+) - // / - // / - - code = """ - float3 ss_to_view(float3 ss_vector, bool is_point) { - float x = ss_vector.x * 2 - 1; - float y = (1 - ss_vector.y) * 2 - 1; - float4 view_vector = mul(float4(x, y, ss_vector.z, is_point), camera_inv_projection); - view_vector.xyz /= view_vector.w; - return view_vector.xyz; - } - - float3 view_to_ss(float3 view_vector, bool is_point) { - float4 ss_vector = mul(float4(view_vector, is_point), camera_projection); - ss_vector.xyz /= ss_vector.w; - ss_vector.xy = ss_vector.xy * float2(0.5, -0.5) + float2(0.5, 0.5); - return ss_vector.xyz; - } - - float3 world_to_view(float3 world_vector, bool is_point) { - float4 view_vector = mul(float4(world_vector, is_point), camera_view); - return view_vector.xyz; - } - - float3 world_to_prev_view(float3 world_vector, bool is_point, bool lock_xyz = 0) { - camera_last_view[3][0] *= !lock_xyz; - camera_last_view[3][1] *= !lock_xyz; - camera_last_view[3][2] *= !lock_xyz; - float4 view_vector = mul(float4(world_vector, is_point), camera_last_view); - return view_vector.xyz; - } - - """ - } - - skinning = { - // This block uses the 'new' syntax as code sharing is very low between languages and it won't be included from any uber shaders. - code = { - glsl = """ - #if defined(SKINNED_1WEIGHT) || defined(SKINNED_2WEIGHTS) || defined(SKINNED_3WEIGHTS) || defined(SKINNED_4WEIGHTS) - #define SKINNED - #endif - - // TODO: Workaround long compile times, since all shaders are currently compiled with skinned option. - #if defined(SKINNED) && defined(SKINNED_DISABLED) - #undef SKINNED - #endif - - #if defined(SKINNED) - #define MAX_BONES 50 - CBUFFER_START(c_skin_matrices) - UNIFORM highp mat4 bones[MAX_BONES]; - #if defined(MOTION_BLUR) - UNIFORM highp mat4 last_bones[MAX_BONES]; - #endif - CBUFFER_END - - #if defined(SKINNED_1WEIGHT) - #define IndexType LOWP float - #define WeightType LOWP float - - vec3 skin_point(vec4 p, IndexType bi, WeightType bw) { - mat4 bone = bones[int(bi)]; - return (p * bone).xyz; - } - - #if defined(MOTION_BLUR) - vec3 skin_point_last_frame(vec4 p, IndexType bi, WeightType bw) { - mat4 bone = last_bones[int(bi)]; - return (p * bone).xyz; - } - #endif - - vec3 skin_vector(vec3 v, IndexType bi, WeightType bw) { - mat4 bone = bones[int(bi)]; - return normalize(v * mat3(bone[0].xyz, bone[1].xyz, bone[2].xyz)); - } - vec3 skin_displacement_delta(vec3 v, IndexType bi, WeightType bw) { - mat4 bone = bones[int(bi)]; - return v * mat3(bone[0].xyz, bone[1].xyz, bone[2].xyz); - } - #elif defined(SKINNED_2WEIGHTS) - #define IndexType LOWP vec2 - #define WeightType LOWP vec2 - - vec3 skin_point(vec4 p, IndexType bi, WeightType bw) { - mat4 bone1 = bones[int(bi.x)]; - mat4 bone2 = bones[int(bi.y)]; - return (bw.x * (p * bone1) + bw.y * (p * bone2)).xyz; - } - #if defined(MOTION_BLUR) - vec3 skin_point_last_frame(vec4 p, IndexType bi, WeightType bw) { - mat4 bone1 = last_bones[int(bi.x)]; - mat4 bone2 = last_bones[int(bi.y)]; - return (bw.x * (p * bone1) + bw.y * (p * bone2)).xyz; - } - #endif - vec3 skin_vector(vec3 v, IndexType bi, WeightType bw) { - mat4 bone1 = bones[int(bi.x)]; - mat4 bone2 = bones[int(bi.y)]; - return normalize( bw.x * (v * mat3(bone1[0].xyz, bone1[1].xyz, bone1[2].xyz)) - + bw.y * (v * mat3(bone2[0].xyz, bone2[1].xyz, bone2[2].xyz))); - } - vec3 skin_displacement_delta(vec3 v, IndexType bi, WeightType bw) { - mat4 bone1 = bones[int(bi.x)]; - mat4 bone2 = bones[int(bi.y)]; - return bw.x * (v * mat3(bone1[0].xyz, bone1[1].xyz, bone1[2].xyz)) - + bw.y * (v * mat3(bone2[0].xyz, bone2[1].xyz, bone2[2].xyz)); - } - #elif defined(SKINNED_3WEIGHTS) - #define IndexType LOWP vec3 - #define WeightType LOWP vec3 - - vec3 skin_point(vec4 p, IndexType bi, WeightType bw) { - mat4 bone1 = bones[int(bi.x)]; - mat4 bone2 = bones[int(bi.y)]; - mat4 bone3 = bones[int(bi.z)]; - return (bw.x * (p * bone1) + bw.y * (p * bone2) + bw.z * (p * bone3)).xyz; - } - #if defined(MOTION_BLUR) - vec3 skin_point_last_frame(vec4 p, IndexType bi, WeightType bw) { - mat4 bone1 = last_bones[int(bi.x)]; - mat4 bone2 = last_bones[int(bi.y)]; - mat4 bone3 = last_bones[int(bi.z)]; - return (bw.x * (p * bone1) + bw.y * (p * bone2) + bw.z * (p * bone3)).xyz; - } - #endif - vec3 skin_vector(vec3 v, IndexType bi, WeightType bw) { - mat4 bone1 = bones[int(bi.x)]; - mat4 bone2 = bones[int(bi.y)]; - mat4 bone3 = bones[int(bi.z)]; - return normalize( bw.x * (v * mat3(bone1[0].xyz, bone1[1].xyz, bone1[2].xyz)) - + bw.y * (v * mat3(bone2[0].xyz, bone2[1].xyz, bone2[2].xyz)) - + bw.z * (v * mat3(bone3[0].xyz, bone3[1].xyz, bone3[2].xyz))); - } - vec3 skin_displacement_delta(vec3 v, IndexType bi, WeightType bw) { - mat4 bone1 = bones[int(bi.x)]; - mat4 bone2 = bones[int(bi.y)]; - mat4 bone3 = bones[int(bi.z)]; - return bw.x * (v * mat3(bone1[0].xyz, bone1[1].xyz, bone1[2].xyz)) - + bw.y * (v * mat3(bone2[0].xyz, bone2[1].xyz, bone2[2].xyz)) - + bw.z * (v * mat3(bone3[0].xyz, bone3[1].xyz, bone3[2].xyz)); - } - #elif defined(SKINNED_4WEIGHTS) - #define IndexType LOWP vec4 - #define WeightType LOWP vec4 - - vec3 skin_point(vec4 p, IndexType bi, WeightType bw) { - mat4 bone1 = bones[int(bi.x)]; - mat4 bone2 = bones[int(bi.y)]; - mat4 bone3 = bones[int(bi.z)]; - mat4 bone4 = bones[int(bi.w)]; - return (bw.x * (p * bone1) + bw.y * (p * bone2) + bw.z * (p * bone3) + bw.w * (p * bone4)).xyz; - } - #if defined(MOTION_BLUR) - vec3 skin_point_last_frame(vec4 p, IndexType bi, WeightType bw) { - mat4 bone1 = last_bones[int(bi.x)]; - mat4 bone2 = last_bones[int(bi.y)]; - mat4 bone3 = last_bones[int(bi.z)]; - mat4 bone4 = last_bones[int(bi.w)]; - return (bw.x * (p * bone1) + bw.y * (p * bone2) + bw.z * (p * bone3) + bw.w * (p * bone4)).xyz; - } - #endif - vec3 skin_vector(vec3 v, IndexType bi, WeightType bw) { - mat4 bone1 = bones[int(bi.x)]; - mat4 bone2 = bones[int(bi.y)]; - mat4 bone3 = bones[int(bi.z)]; - mat4 bone4 = bones[int(bi.w)]; - return normalize( bw.x * (v * mat3(bone1[0].xyz, bone1[1].xyz, bone1[2].xyz)) - + bw.y * (v * mat3(bone2[0].xyz, bone2[1].xyz, bone2[2].xyz)) - + bw.z * (v * mat3(bone3[0].xyz, bone3[1].xyz, bone3[2].xyz)) - + bw.w * (v * mat3(bone4[0].xyz, bone4[1].xyz, bone4[2].xyz))); - } - vec3 skin_displacement_delta(vec3 v, IndexType bi, WeightType bw) { - mat4 bone1 = bones[int(bi.x)]; - mat4 bone2 = bones[int(bi.y)]; - mat4 bone3 = bones[int(bi.z)]; - mat4 bone4 = bones[int(bi.w)]; - return bw.x * (v * mat3(bone1[0].xyz, bone1[1].xyz, bone1[2].xyz)) - + bw.y * (v * mat3(bone2[0].xyz, bone2[1].xyz, bone2[2].xyz)) - + bw.z * (v * mat3(bone3[0].xyz, bone3[1].xyz, bone3[2].xyz)) - + bw.z * (v * mat3(bone4[0].xyz, bone4[1].xyz, bone4[2].xyz)); - } - #endif - - in IndexType blendindices; - in WeightType blendweights; - #endif - """ - - hlsl = """ - #if defined(SKINNED_1WEIGHT) || defined(SKINNED_2WEIGHTS) || defined(SKINNED_3WEIGHTS) || defined(SKINNED_4WEIGHTS) - #define SKINNED - #endif - - // TODO: Workaround long compile times, since all shaders are currently compiled with skinned option. - #if defined(SKINNED) && defined(SKINNED_DISABLED) - #undef SKINNED - #endif - - #if defined(SKINNED) - CBUFFER_START(c_skin_matrices) - #if defined(RENDERER_GL2) - #define MAX_BONES 50 - #else - #define MAX_BONES 100 - #endif - float4x4 bones[MAX_BONES]; - - #if defined(MOTION_BLUR) - float4x4 last_bones[MAX_BONES]; - #endif - CBUFFER_END - - #if defined(SKINNED_1WEIGHT) - #define IndexType float1 - #define WeightType float1 - - #if defined(GNM) - // Avoids 'unreferenced variable' warning on ps4 - #define WEIGHT_PARAM_NAME - #else - #define WEIGHT_PARAM_NAME bw - #endif - - inline float3 skin_point(in float4 p, in IndexType bi, in WeightType WEIGHT_PARAM_NAME) { - return mul(p, (bones[(int)bi.x])).xyz; - } - #if defined(MOTION_BLUR) - inline float3 skin_point_last_frame(in float4 p, in IndexType bi, in WeightType WEIGHT_PARAM_NAME) { - return mul(p, (last_bones[(int)bi.x])).xyz; - } - #endif - inline float3 skin_vector(in float3 v, in IndexType bi, in WeightType WEIGHT_PARAM_NAME) { - return normalize(mul(v, (float3x3)(bones[(int)bi.x]))); - } - inline float3 skin_displacement_delta(in float3 v, in IndexType bi, in WeightType WEIGHT_PARAM_NAME) { - return mul(v, (float3x3)(bones[(int)bi.x])); - } - #elif defined(SKINNED_2WEIGHTS) - #define IndexType float2 - #define WeightType float2 - - inline float3 skin_point(in float4 p, in IndexType bi, in WeightType bw) { - return bw.x * mul(p, (bones[(int)bi.x])).xyz + bw.y * mul(p, (bones[(int)bi.y])).xyz; - } - #if defined(MOTION_BLUR) - inline float3 skin_point_last_frame(in float4 p, in IndexType bi, in WeightType bw) { - return bw.x * mul(p, (last_bones[(int)bi.x])).xyz + bw.y * mul(p, (last_bones[(int)bi.y])).xyz; - } - #endif - inline float3 skin_vector(in float3 v, in IndexType bi, in WeightType bw) { - return normalize(bw.x * mul(v, (float3x3)(bones[(int)bi.x])) + bw.y * mul(v, (float3x3)(bones[(int)bi.y]))); - } - inline float3 skin_displacement_delta(in float3 v, in IndexType bi, in WeightType bw) { - return bw.x * mul(v, (float3x3)(bones[(int)bi.x])) + bw.y * mul(v, (float3x3)(bones[(int)bi.y])).xyz; - } - #elif defined(SKINNED_3WEIGHTS) - #define IndexType float3 - #define WeightType float3 - - inline float3 skin_point(in float4 p, in IndexType bi, in WeightType bw) { - return bw.x * mul(p, (bones[(int)bi.x])).xyz + bw.y * mul(p, (bones[(int)bi.y])).xyz + bw.z * mul(p, (bones[(int)bi.z])).xyz; - } - #if defined(MOTION_BLUR) - inline float3 skin_point_last_frame(in float4 p, in IndexType bi, in WeightType bw) { - return bw.x * mul(p, (last_bones[(int)bi.x])).xyz + bw.y * mul(p, (last_bones[(int)bi.y])).xyz + bw.z * mul(p, (last_bones[(int)bi.z])).xyz; - } - #endif - inline float3 skin_vector(in float3 v, in IndexType bi, in WeightType bw) { - return normalize(bw.x * mul(v, (float3x3)(bones[(int)bi.x])) + bw.y * mul(v, (float3x3)(bones[(int)bi.y])) + bw.z * mul(v, (float3x3)(bones[(int)bi.z]))); - } - inline float3 skin_displacement_delta(in float3 v, in IndexType bi, in WeightType bw) { - return bw.x * mul(v, (float3x3)(bones[(int)bi.x])) + bw.y * mul(v, (float3x3)(bones[(int)bi.y])) + bw.z * mul(v, (float3x3)(bones[(int)bi.z])); - } - #elif defined(SKINNED_4WEIGHTS) - #define IndexType float4 - #define WeightType float4 - - inline float3 skin_point(in float4 p, in IndexType bi, in WeightType bw) { - return bw.x * mul(p, (bones[(int)bi.x])).xyz + bw.y * mul(p, (bones[(int)bi.y])).xyz + bw.z * mul(p, (bones[(int)bi.z])).xyz + bw.w * mul(p, (bones[(int)bi.w])).xyz; - } - #if defined(MOTION_BLUR) - inline float3 skin_point_last_frame(in float4 p, in IndexType bi, in WeightType bw) { - return bw.x * mul(p, (last_bones[(int)bi.x])).xyz + bw.y * mul(p, (last_bones[(int)bi.y])).xyz + bw.z * mul(p, (last_bones[(int)bi.z])).xyz + bw.w * mul(p, (last_bones[(int)bi.w])).xyz; - } - #endif - inline float3 skin_vector(in float3 v, in IndexType bi, in WeightType bw) { - return normalize(bw.x * mul(v, (float3x3)(bones[(int)bi.x])) + bw.y * mul(v, (float3x3)(bones[(int)bi.y])) + bw.z * mul(v, (float3x3)(bones[(int)bi.z])) + bw.w * mul(v, (float3x3)(bones[(int)bi.w]))); - } - inline float3 skin_displacement_delta(in float3 v, in IndexType bi, in WeightType bw) { - return bw.x * mul(v, (float3x3)(bones[(int)bi.x])) + bw.y * mul(v, (float3x3)(bones[(int)bi.y])) + bw.z * mul(v, (float3x3)(bones[(int)bi.z])) + bw.w * mul(v, (float3x3)(bones[(int)bi.w])); - } - #endif - - #define BLENDINDEXSEMANTIC BLENDINDICES - - #define SKIN_INPUT \ - IndexType blendindices : BLENDINDEXSEMANTIC; \ - WeightType blendweights : BLENDWEIGHTS; - #else - #define SKIN_INPUT - #endif - """ - } - } - - fog = { - vp_code = { ref = "code" } - fp_code = { ref = "code" } - code=""" - CBUFFER_START(c_fog) - UNIFORM float2 fog_depth_range; - float2 height_fog_offset_falloff; // TODO: merge this param with fog_depth_range? - float fog_type; - UNIFORM float3 fog_color; - #if !defined(HAS_SUN_DIRECTION) - UNIFORM float3 sun_direction; - #endif - #if !defined(HAS_SUN_COLOR) - UNIFORM float3 sun_color; - #endif - UNIFORM float3 fog_sun_blend; - UNIFORM float fog_enabled; - CBUFFER_END - - #define DEFAULT_EXP_HEIGHT 0 - #define EXP_HEIGHT 1 - #define EXP 2 - #define LINEAR 3 - - half4 apply_fog(half4 c, float3 wp, float d) { - if (fog_enabled < 1.0) - return c; - - float start = fog_depth_range.x; - float end = fog_depth_range.y; - float b = 1.f / (end-start); - - #if defined(RENDERER_GL) - float3 view_dir = normalize(new_half3(camera_world[0].z, camera_world[1].z, camera_world[2].z) - wp); - float camera_world_m32 = camera_world[2].z; - #else - float3 view_dir = normalize(camera_world._m30_m31_m32 - wp); - float camera_world_m32 = camera_world._m32; - #endif - - float dist = d - start; - - float a = 0.0; - [branch] - if (fog_type == DEFAULT_EXP_HEIGHT) { - a = saturate(exp(-camera_world._m32 * b) * (1.0 - exp(-dist * -view_dir.z * b)) / -view_dir.z); - } else if (fog_type == EXP_HEIGHT) { - a = saturate(exp((height_fog_offset_falloff.x - wp.z)/height_fog_offset_falloff.y) * (1.0 - exp(-dist * b))); - } else if (fog_type == EXP) { - a = 1.0 - saturate(exp(-dist * b)); - } else { - a = d > start ? saturate((d-start) * b) : 0; - } - - half sa = fog_sun_blend.x * pow(saturate(dot(view_dir, sun_direction)), fog_sun_blend.y); - float3 fog_c = lerp(fog_color, fog_sun_blend.z * sun_color, sa); - return new_half4_xyz(lerp(c.rgb, fog_c, a), c.a); - } - - float4 calc_fog_vs(float3 wp, float d) { - if (fog_enabled < 1.0) - return float4(0,0,0,0); - - float start = fog_depth_range.x; - float end = fog_depth_range.y; - float b = 1.f / (end-start); - - #if defined(RENDERER_GL) - float3 view_dir = normalize(new_half3(camera_world[0].z, camera_world[1].z, camera_world[2].z) - wp); - float camera_world_m32 = camera_world[2].z; - #else - float3 view_dir = normalize(camera_world._m30_m31_m32 - wp); - float camera_world_m32 = camera_world._m32; - #endif - - float dist = d - start; - - float a = 0.0; - [branch] - if (fog_type == DEFAULT_EXP_HEIGHT) { - a = saturate(exp(-camera_world._m32 * b) * (1.0 - exp(-dist * -view_dir.z * b)) / -view_dir.z); - } else if (fog_type == EXP_HEIGHT) { - a = saturate(exp((height_fog_offset_falloff.x - wp.z)/height_fog_offset_falloff.y) * (1.0 - exp(-dist * b))); - } else if (fog_type == EXP) { - a = 1.0 - saturate(exp(-dist * b)); - } else { - a = d > start ? saturate((d-start) * b) : 0; - } - - half sa = fog_sun_blend.x * pow(saturate(dot(view_dir, sun_direction)), fog_sun_blend.y); - float3 fog_c = lerp(fog_color, fog_sun_blend.z * sun_color, sa); - return float4(fog_c, a); - - } - - #undef DEFAULT_EXP_HEIGHT - #undef EXP_HEIGHT - #undef EXP - #undef LINEAR - """ - } - - /*shadow_bias = { - code = """ - float apply_shadow_bias(float depth) { - const float min_bias = 0.005; - const float max_bias = 0.2; - const float blend_distance = 50.0; - depth -= lerp(min_bias, max_bias, saturate(depth / blend_distance)); - return depth; - } - """ - fp_code = { ref = "code" } - } - */ - color_management = { - code=""" - #if defined(RENDERER_GL) - #define splat3(c) vec3(c) - #else - #define splat3(c) c - #endif - - static const float3 luminance_vector = float3(0.2127, 0.7152, 0.0721); - static const half min_positive_f16 = 0.000061; - - float3 filmic_tone_mapping(float3 lin_x) { - float3 x = max(splat3(0.f), lin_x - splat3(0.004f)); - return (x*(6.2f*x + splat3(0.5f)))/(x*(6.2f*x + splat3(1.7f)) + splat3(0.06f)); - } - - float3 safe_range_tone_map(float3 value) { - float lum = max(dot(value.rgb, luminance_vector), min_positive_f16); - value.rgb /= (1.0 + lum); - - return value; - } - - float3 inv_safe_range_tone_map(float3 value) { - float lum = dot(value.rgb, luminance_vector); - value.rgb /= max((1.0 - lum), min_positive_f16); - - return value; - } - - float3 safe_range_tone_map_offset(float3 value, float offset) { - float lum = max(dot(value.rgb, luminance_vector), min_positive_f16); - value.rgb /= (offset + lum); - - return value; - } - - float3 inv_safe_range_tone_map_offset(float3 value, float offset) { - float lum = dot(value.rgb, luminance_vector); - value.rgb /= max((offset - lum), min_positive_f16); - - return value; - } - - float luminance(float3 value) { - return dot(value, luminance_vector); - } - - #undef splat3 - """ - fp_code = { ref = "code" } - } - - billboard_transformation = { - code = """ - // TODO: reuse code - void get_billboard_data_from_position(in float3 world_pos, in float3 camera_pos, in float4x4 camera_view, inout float4 position, out float4 wp, out float3 normal, out float3 tangent, out float3 binormal) { - wp = float4(world_pos, 1.0); - #if defined(BILLBOARD_TANGENT_ALIGNED) || defined(BILLBOARD_CAMERA_ALIGNED) - float3 eye_dir = normalize(camera_pos - wp.rgb); - #endif - #if defined(BILLBOARD_TANGENT_ALIGNED) - #if defined(BILLBOARD_TANGENT_ALIGNED_X_LOCKED) - float3 x_axis = float3(1, 0, 0); - float3 y_axis = normalize(cross(eye_dir, x_axis)); - #elif defined(BILLBOARD_TANGENT_ALIGNED_Y_LOCKED) - float3 x_axis = float3(0, 1, 0); - float3 y_axis = normalize(cross(eye_dir, x_axis)); - #else - float3 y_axis = float3(0, 0, 1); - float3 x_axis = normalize(cross(y_axis, eye_dir)); - #endif - #elif defined(BILLBOARD_CAMERA_ALIGNED) - float3 y_axis = float3(0, 0, 1); - float3 x_axis = normalize(cross(y_axis, eye_dir)); - y_axis = cross(eye_dir, x_axis); - #else - float3 x_axis = camera_view._m00_m10_m20; - float3 y_axis = camera_view._m02_m12_m22; - #endif - position = float4(x_axis * position.x + y_axis * position.y, 1.0); - wp.xyz += position.xyz; - - // Calculate normals and tangent info - #if defined(BILLBOARD_TANGENT_ALIGNED) - normal = cross(x_axis, y_axis); - #elif defined(BILLBOARD_CAMERA_ALIGNED) - normal = eye_dir; // TODO: is this same as -camera_view._m01_m11_m21? - #else - normal = -camera_view._m01_m11_m21; - #endif - #if defined(BILLBOARD_SPHERICAL_NORMAL) - // TODO: re-calculate tangent and binormal - normal = normalize(lerp(position, normal, 0.5)); - #endif - tangent = x_axis; - binormal = y_axis; - } - - void get_billboard_positions_from_position(in float3 world_pos, in float3 camera_pos, in float4x4 camera_view, inout float4 position, out float4 wp) { - wp = float4(world_pos, 1.0); - #if defined(BILLBOARD_TANGENT_ALIGNED) || defined(BILLBOARD_CAMERA_ALIGNED) - float3 eye_dir = normalize(camera_pos - wp.rgb); - #endif - #if defined(BILLBOARD_TANGENT_ALIGNED) - #if defined(BILLBOARD_TANGENT_ALIGNED_X_LOCKED) - float3 x_axis = float3(1, 0, 0); - float3 y_axis = normalize(cross(eye_dir, x_axis)); - #elif defined(BILLBOARD_TANGENT_ALIGNED_Y_LOCKED) - float3 x_axis = float3(0, 1, 0); - float3 y_axis = normalize(cross(eye_dir, x_axis)); - #else - float3 y_axis = float3(0, 0, 1); - float3 x_axis = normalize(cross(y_axis, eye_dir)); - #endif - #elif defined(BILLBOARD_CAMERA_ALIGNED) - float3 y_axis = float3(0, 0, 1); - float3 x_axis = normalize(cross(y_axis, eye_dir)); - y_axis = cross(eye_dir, x_axis); - #else - float3 x_axis = camera_view._m00_m10_m20; - float3 y_axis = camera_view._m02_m12_m22; - #endif - position = float4(x_axis * position.x + y_axis * position.y, 1.0); - wp.xyz += position.xyz; - } - - void get_billboard_data_from_direction(in float3 direction, inout float4 position, out float4 wp, out float3 normal, out float3 tangent, out float3 binormal) { - wp = float4(-direction, 1.0); - float3 y_axis = float3(0, 0, 1); - float3 x_axis = normalize(cross(y_axis, direction)); - y_axis = cross(direction, x_axis); - position = float4(x_axis * position.x + y_axis * position.y, 1.0); - wp.xyz += position.xyz; - - // Calculate normals and tangent info - normal = direction; - #if defined(BILLBOARD_SPHERICAL_NORMAL) - // TODO: re-calculate tangent and binormal - normal = normalize(lerp(position, normal, 0.5)); - #endif - tangent = x_axis; - binormal = y_axis; - } - - void get_billboard_positions_from_direction(in float3 direction, inout float4 position, out float4 wp) { - wp = float4(-direction, 1.0); - float3 y_axis = float3(0, 0, 1); - float3 x_axis = normalize(cross(y_axis, direction)); - y_axis = cross(direction, x_axis); - position = float4(x_axis * position.x + y_axis * position.y, 1.0); - wp.xyz += position.xyz; - } - """ - fp_code = { ref = "code" } - } - - taa_offsets = { - code=""" - #if !defined(RENDERER_GL) - CBUFFER_START(temporal_effects) - UNIFORM float temporal_effects_enabled; - CBUFFER_END - - // Halton offsets - #define NUM_HALTON_OFFSETS 8 - #define BLACKMAN_HARRIS_SHARPNESS 2.0 - - static const float2 halton_offsets[] = { - float2((1.f/2.f - 0.5f), (1.f/3.f - 0.5f)), - float2((1.f/4.f - 0.5f), (2.f/3.f - 0.5f)), - float2((3.f/4.f - 0.5f), (1.f/9.f - 0.5f)), - float2((1.f/8.f - 0.5f), (4.f/9.f - 0.5f)), - float2((5.f/8.f - 0.5f), (7.f/9.f - 0.5f)), - float2((3.f/8.f - 0.5f), (2.f/9.f - 0.5f)), - float2((7.f/8.f - 0.5f), (5.f/9.f - 0.5f)), - float2((1.f/16.f - 0.5f), (8.f/9.f - 0.5f)) - }; - - // Blackman-Harris pre calculated weights - float gaussian_blackman_harris(float2 pos) { - float x = pos.x * BLACKMAN_HARRIS_SHARPNESS; - float y = pos.y * BLACKMAN_HARRIS_SHARPNESS; - return exp(-2.29f * (x * x + y * y)); - } - - static const int2 neighbor_offsets_i[9] = { - int2(-1, -1), - int2( 0, -1), - int2( 1, -1), - int2(-1, 0), - int2( 0, 0), - int2( 1, 0), - int2(-1, 1), - int2( 0, 1), - int2( 1, 1) - }; - - static const float2 neighbor_offsets[9] = { - neighbor_offsets_i[0], - neighbor_offsets_i[1], - neighbor_offsets_i[2], - neighbor_offsets_i[3], - neighbor_offsets_i[4], - neighbor_offsets_i[5], - neighbor_offsets_i[6], - neighbor_offsets_i[7], - neighbor_offsets_i[8] - }; - - static const float blackman_harris_sum0 = - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[0]) + - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[0]) + - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[0]) + - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[0]) + - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[0]) + - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[0]) + - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[0]) + - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[0]) + - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[0]); - - static const float blackman_harris_weights0[9] = { - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[0]) / blackman_harris_sum0, - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[0]) / blackman_harris_sum0, - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[0]) / blackman_harris_sum0, - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[0]) / blackman_harris_sum0, - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[0]) / blackman_harris_sum0, - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[0]) / blackman_harris_sum0, - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[0]) / blackman_harris_sum0, - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[0]) / blackman_harris_sum0, - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[0]) / blackman_harris_sum0 - }; - - static const float blackman_harris_sum1 = - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[1]) + - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[1]) + - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[1]) + - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[1]) + - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[1]) + - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[1]) + - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[1]) + - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[1]) + - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[1]); - - static const float blackman_harris_weights1[9] = { - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[1]) / blackman_harris_sum1, - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[1]) / blackman_harris_sum1, - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[1]) / blackman_harris_sum1, - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[1]) / blackman_harris_sum1, - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[1]) / blackman_harris_sum1, - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[1]) / blackman_harris_sum1, - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[1]) / blackman_harris_sum1, - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[1]) / blackman_harris_sum1, - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[1]) / blackman_harris_sum1 - }; - - static const float blackman_harris_sum2 = - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[2]) + - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[2]) + - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[2]) + - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[2]) + - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[2]) + - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[2]) + - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[2]) + - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[2]) + - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[2]); - - static const float blackman_harris_weights2[9] = { - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[2]) / blackman_harris_sum2, - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[2]) / blackman_harris_sum2, - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[2]) / blackman_harris_sum2, - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[2]) / blackman_harris_sum2, - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[2]) / blackman_harris_sum2, - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[2]) / blackman_harris_sum2, - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[2]) / blackman_harris_sum2, - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[2]) / blackman_harris_sum2, - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[2]) / blackman_harris_sum2 - }; - - static const float blackman_harris_sum3 = - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[3]) + - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[3]) + - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[3]) + - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[3]) + - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[3]) + - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[3]) + - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[3]) + - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[3]) + - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[3]); - - static const float blackman_harris_weights3[9] = { - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[3]) / blackman_harris_sum3, - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[3]) / blackman_harris_sum3, - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[3]) / blackman_harris_sum3, - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[3]) / blackman_harris_sum3, - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[3]) / blackman_harris_sum3, - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[3]) / blackman_harris_sum3, - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[3]) / blackman_harris_sum3, - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[3]) / blackman_harris_sum3, - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[3]) / blackman_harris_sum3 - }; - - static const float blackman_harris_sum4 = - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[4]) + - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[4]) + - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[4]) + - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[4]) + - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[4]) + - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[4]) + - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[4]) + - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[4]) + - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[4]); - - static const float blackman_harris_weights4[9] = { - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[4]) / blackman_harris_sum4, - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[4]) / blackman_harris_sum4, - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[4]) / blackman_harris_sum4, - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[4]) / blackman_harris_sum4, - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[4]) / blackman_harris_sum4, - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[4]) / blackman_harris_sum4, - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[4]) / blackman_harris_sum4, - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[4]) / blackman_harris_sum4, - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[4]) / blackman_harris_sum4 - }; - - static const float blackman_harris_sum5 = - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[5]) + - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[5]) + - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[5]) + - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[5]) + - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[5]) + - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[5]) + - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[5]) + - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[5]) + - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[5]); - - static const float blackman_harris_weights5[9] = { - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[5]) / blackman_harris_sum5, - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[5]) / blackman_harris_sum5, - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[5]) / blackman_harris_sum5, - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[5]) / blackman_harris_sum5, - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[5]) / blackman_harris_sum5, - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[5]) / blackman_harris_sum5, - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[5]) / blackman_harris_sum5, - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[5]) / blackman_harris_sum5, - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[5]) / blackman_harris_sum5 - }; - - static const float blackman_harris_sum6 = - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[6]) + - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[6]) + - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[6]) + - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[6]) + - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[6]) + - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[6]) + - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[6]) + - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[6]) + - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[6]); - - static const float blackman_harris_weights6[9] = { - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[6]) / blackman_harris_sum6, - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[6]) / blackman_harris_sum6, - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[6]) / blackman_harris_sum6, - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[6]) / blackman_harris_sum6, - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[6]) / blackman_harris_sum6, - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[6]) / blackman_harris_sum6, - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[6]) / blackman_harris_sum6, - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[6]) / blackman_harris_sum6, - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[6]) / blackman_harris_sum6 - }; - - static const float blackman_harris_sum7 = - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[7]) + - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[7]) + - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[7]) + - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[7]) + - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[7]) + - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[7]) + - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[7]) + - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[7]) + - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[7]); - - static const float blackman_harris_weights7[9] = { - gaussian_blackman_harris(neighbor_offsets[0] + halton_offsets[7]) / blackman_harris_sum7, - gaussian_blackman_harris(neighbor_offsets[1] + halton_offsets[7]) / blackman_harris_sum7, - gaussian_blackman_harris(neighbor_offsets[2] + halton_offsets[7]) / blackman_harris_sum7, - gaussian_blackman_harris(neighbor_offsets[3] + halton_offsets[7]) / blackman_harris_sum7, - gaussian_blackman_harris(neighbor_offsets[4] + halton_offsets[7]) / blackman_harris_sum7, - gaussian_blackman_harris(neighbor_offsets[5] + halton_offsets[7]) / blackman_harris_sum7, - gaussian_blackman_harris(neighbor_offsets[6] + halton_offsets[7]) / blackman_harris_sum7, - gaussian_blackman_harris(neighbor_offsets[7] + halton_offsets[7]) / blackman_harris_sum7, - gaussian_blackman_harris(neighbor_offsets[8] + halton_offsets[7]) / blackman_harris_sum7 - }; - - static const float blackman_harris_weights[NUM_HALTON_OFFSETS][9] = { - blackman_harris_weights0, - blackman_harris_weights1, - blackman_harris_weights2, - blackman_harris_weights3, - blackman_harris_weights4, - blackman_harris_weights5, - blackman_harris_weights6, - blackman_harris_weights7 - }; - - - float2 get_vs_halton_offset(uint frame_number) - { - // Multiply the halton offset by 2 since we are adding the offset in view space (non projected frustrum width and height ranges [-1, 1]) - #if !defined(RENDERER_GL) - float enabled = temporal_effects_enabled * taa_enabled * !debug_rendering; - #if defined(D3D11)/* || defined(D3D12)*/ // we don't have baking support for D3D12 - enabled *= !capture_cubemap; - #endif - return (halton_offsets[frame_number % NUM_HALTON_OFFSETS] / back_buffer_size) / viewport.xy * 2 * enabled; - #else - return float2(0,0); - #endif - } - #endif - """ - } -} diff --git a/vmf/core/stingray_renderer/shader_libraries/gui.shader_source b/vmf/core/stingray_renderer/shader_libraries/gui.shader_source deleted file mode 100644 index e98ff09..0000000 --- a/vmf/core/stingray_renderer/shader_libraries/gui.shader_source +++ /dev/null @@ -1,613 +0,0 @@ -includes = ["core/stingray_renderer/shader_libraries/common.shader_source"] - -render_states = { - gui_gradient = { - inherits = "opacity" - states = { - z_enable = "false" - z_write_enable = "false" - defined_WRITE_MASK = { - defined_ADDITIVE_BLEND = { - blend_enable = "true" - blend_op = "blend_op_add" - dest_blend = "blend_one" - src_blend = "blend_one" - } - ndefined_ADDITIVE_BLEND = { - blend_enable = "false" - } - write_mask0 = "red" - } - defined_MASKED = { - blend_enable = "true" - blend_op = "blend_op_add" - dest_blend = "blend_inv_src_alpha" - src_blend = "blend_src_alpha" - } - } - } -} - -hlsl_shaders = { - gui_gradient = { - includes = [ "common" ] - - samplers = { - defined_DIFFUSE_MAP = { - defined_ATLAS_COLOR_LOOKUP = { - defined_ANISOTROPIC = { - diffuse_map = { sampler_states = "clamp_anisotropic" } - } - ndefined_ANISOTROPIC = { - diffuse_map = { sampler_states = "clamp_point" } - } - } - ndefined_ATLAS_COLOR_LOOKUP = { - defined_CLAMP_POINT ={ - diffuse_map = { sampler_states = "clamp_point" } - } - ndefined_CLAMP_POINT = { - diffuse_map = { sampler_states = "clamp_linear" } - } - } - } - defined_DIFFUSE_MAP_TWO = { - diffuse_map = { sampler_states = "clamp_linear" } - diffuse_map_two = { sampler_states = "clamp_linear" } - } - defined_DIFFUSE_MAP_THREE = { - diffuse_map = { sampler_states = "clamp_linear" } - diffuse_map_two = { sampler_states = "clamp_linear" } - diffuse_map_three = { sampler_states = "clamp_linear" } - } - defined_DIFFUSE_MAP_FOUR = { - diffuse_map = { sampler_states = "clamp_linear" } - diffuse_map_two = { sampler_states = "clamp_linear" } - diffuse_map_three = { sampler_states = "clamp_linear" } - diffuse_map_four = { sampler_states = "clamp_linear" } - } - defined_DIFFUSE_MAP_FIVE = { - diffuse_map = { sampler_states = "clamp_linear" } - diffuse_map_two = { sampler_states = "clamp_linear" } - diffuse_map_three = { sampler_states = "clamp_linear" } - diffuse_map_four = { sampler_states = "clamp_linear" } - diffuse_map_five = { sampler_states = "clamp_linear" } - } - defined_DIFFUSE_MAP_SIX = { - diffuse_map = { sampler_states = "clamp_linear" } - diffuse_map_two = { sampler_states = "clamp_linear" } - diffuse_map_three = { sampler_states = "clamp_linear" } - diffuse_map_four = { sampler_states = "clamp_linear" } - diffuse_map_five = { sampler_states = "clamp_linear" } - diffuse_map_six = { sampler_states = "clamp_linear" } - } - defined_GRADIENT = { - gradient_map = { sampler_states = "clamp_anisotropic" } - } - defined_MASKED = { - overlay_mask = { sampler_states = "clamp_point" } - } - defined_PATTERN_TINTING = { - color_atlas = { sampler_states = "clamp_point" } - material_map = { sampler_states = "clamp_point" } - } - defined_DETAIL_TEXTURE = { - detail_texture = { sampler_states = "wrap_linear" } - } - defined_COLOR_TINT_MAP = { - color_tint_map = { sampler_states = "clamp_linear" } - } - defined_DISTORTION = { - distortion_map = { sampler_states = "wrap_linear" } - } - } - - code=""" - #if defined(DIFFUSE_MAP) || defined(DIVISION) || defined(PATTERN_TINTING) || defined(ATLAS_COLOR_LOOKUP) || defined(CIRCULAR_MASK) || defined(CIRCULAR_GRADIENT) || defined(DIFFUSE_MAP_TWO) || defined(DIFFUSE_MAP_THREE) || defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - #define UV0 - #endif - - #if defined(MASKED) - DECLARE_SAMPLER_2D(overlay_mask); - #endif - - #if defined(DETAIL_TEXTURE) - DECLARE_SAMPLER_2D(detail_texture); // exports={ name="Detail Map" type="resource" } - #endif - - #if defined(DIFFUSE_MAP) - DECLARE_SAMPLER_2D(diffuse_map); // exports={ name="Diffuse Map" type="resource" } - #endif - - #if defined(DIFFUSE_MAP_TWO) - DECLARE_SAMPLER_2D(diffuse_map); // exports={ name="Diffuse Map" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_two); // exports={ name="Diffuse Map Two" type="resource" } - #endif - - #if defined(DIFFUSE_MAP_THREE) - DECLARE_SAMPLER_2D(diffuse_map); // exports={ name="Diffuse Map" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_two); // exports={ name="Diffuse Map Two" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_three); // exports={ name="Diffuse Map Three" type="resource" } - #endif - - #if defined(DIFFUSE_MAP_FOUR) - DECLARE_SAMPLER_2D(diffuse_map); // exports={ name="Diffuse Map" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_two); // exports={ name="Diffuse Map Two" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_three); // exports={ name="Diffuse Map Three" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_four); // exports={ name="Diffuse Map Four" type="resource" } - #endif - - #if defined(DIFFUSE_MAP_FIVE) - DECLARE_SAMPLER_2D(diffuse_map); // exports={ name="Diffuse Map" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_two); // exports={ name="Diffuse Map Two" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_three); // exports={ name="Diffuse Map Three" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_four); // exports={ name="Diffuse Map Four" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_five); // exports={ name="Diffuse Map Five" type="resource" } - #endif - - #if defined(DIFFUSE_MAP_SIX) - DECLARE_SAMPLER_2D(diffuse_map); // exports={ name="Diffuse Map" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_two); // exports={ name="Diffuse Map Two" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_three); // exports={ name="Diffuse Map Three" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_four); // exports={ name="Diffuse Map Four" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_five); // exports={ name="Diffuse Map Five" type="resource" } - DECLARE_SAMPLER_2D(diffuse_map_six); // exports={ name="Diffuse Map Six" type="resource" } - #endif - - #if defined(GRADIENT) - DECLARE_SAMPLER_2D(gradient_map); // exports={ name="Gradient Map" type="resource" } - #endif - - #if defined(DISTORTION) - DECLARE_SAMPLER_2D(distortion_map); // exports={ name="Distortion Map" type="resource" } - #endif - - #if defined(PATTERN_TINTING) - DECLARE_SAMPLER_2D(color_atlas); // exports={ name="Color Atlas" type="resource" } - DECLARE_SAMPLER_2D(material_map); // exports={ name="Material Map" type="resource" } - #endif - - #if defined(COLOR_TINT_MAP) - DECLARE_SAMPLER_2D(color_tint_map); // exports={ name="Color Tint Map" type="resource" } - #endif - - struct VS_INPUT { - float4 position : POSITION; - #if defined(DIFFUSE_MAP_TWO) || defined(DIFFUSE_MAP_THREE) || defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - float3 normal : NORMAL; - #endif - float4 color : COLOR; - #if defined(UV0) - float2 uv : TEXCOORD0; - #endif - }; - - struct PS_INPUT { - float4 position : SV_POSITION; - float4 color : COLOR; - #if defined(DIFFUSE_MAP_TWO) || defined(DIFFUSE_MAP_THREE) || defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - float page : TEXCOORD1; - #endif - #if defined(UV0) - float2 uv : TEXCOORD0; - #endif - }; - - inline float2 scale_material_uv( float2 material_uv, float pattern_variation ) { - float pattern_u = fmod(pattern_variation,2.0f) * 0.5f; - float pattern_v = floor(pattern_variation / 2.0f) * 0.5; - return float2((material_uv.x * 0.5) + pattern_u, (material_uv.y * 0.5) + pattern_v); - } - - inline float2 scale_uv_coat_of_arms( float2 uv, float variation, float2 atlas_fields ) { - float step_u = (1.0f/atlas_fields.x); - float step_v = (1.0f/atlas_fields.y); - float pattern_u = fmod( variation, atlas_fields.x) * step_u; - float pattern_v = floor( variation / atlas_fields.x ) * step_v; - - return float2(uv.x * step_u + pattern_u, uv.y * step_v + pattern_v); - } - - inline float2 scale_uv_coat_of_arms_atlas( float2 uv, float2 offset, float2 scale) - { - float2 scaled_uv = uv * scale + offset; - return scaled_uv; - } - - - CBUFFER_START(c0) - float4x4 world_view_proj; - float threshold_fade; // exports = { name="Threshold Fade" type="scalar" value=0.05 min=0.0 max=1 step=0.001 } - #if defined(GRADIENT) - float gradient_threshold; // exports = { Name="Gradient threshold" type="scalar" value=0.37 min=0 max=1 step=0.00001 } - #endif - #if defined(PATTERN_TINTING) - float pattern_variation; // exports = { name="Pattern Variation" type="scalar" value=0.0 min=0.0 max=3.0 step=1.0 } - float atlas_variation; // exports = { name="Armour Atlas Variation" type="scalar" value=0.0 min=0.0 max=31.0 step=1.0 } - float use_grayscale = 0; - #endif - #if defined(ATLAS_COLOR_LOOKUP) - float2 atlas_tiles; // exports = { name="Atlas tiles" type="vector2" value=[128.0 1.0] min=[1.0 1.0] max=[255.0 255.0] step=[1.0 1.0] } - #endif - #if defined(CIRCULAR_MASK) - float radial_threshold; // exports = { name="Radial Threshold" type="scalar" value=0.5 min=0.0 max=1.0 step=0.0001 } - float fade_threshold; // exports = { name="Fade Threshold" type="scalar" value=0.5 min=0.0001 max=1.0 step=0.0001 } - #if defined(UV_SCALE) - float2 uv_scale; // exports = { name="UV Scale" type="vector2" value=[0.0 0.0] min=[0.001 0.001] max=[1 1] step=[0.0001 0.0001] } - #endif - #endif - #if defined(CIRCULAR_GRADIENT) - float4 from_color; // exports = { name="Gradient From Color" type="vector4" value=[0.0 0.0 0.0 0.0] min=[0 0 0 0] max=[1 1 1 1] step=[0.0001 0.0001 0.0001 0.0001] } - float4 to_color; // exports = { name="Gradient To Color" type="vector4" value=[0.0 0.0 0.0 0.0] min=[0 0 0 0] max=[1 1 1 1] step=[0.0001 0.0001 0.0001 0.0001] } - float exponent; // exports = { name="Gradient exponent" type="scalar" value=1 min=0 max=10.0 step=0.0001 } - float scale; // exports = { name="Gradient scale" type="scalar" value=1 min=0 max=10.0 step=0.0001 } - #endif - #if defined(DISTANCE_FIELD) - float smoothing_denominator; // exports = { name="Smoothing Scale" type="scalar" value=18 min=2 max=100.0 step=0.001 } - float outline_color; // exports = { name="Outline Color" type="vector3" value=[0.0 0.0 0.0] min=[0.0 0.0 0.0] max=[1 1 1] step=[0.0001 0.0001 0.0001] } - float2 min_value; // exports = { name="Min Outline" type="vector2" value=[0.0 0.0] min=[0.0 0.0] max=[1 1] step=[0.0001 0.0001] } - float2 max_value; // exports = { name="Max Outline" type="vector2" value=[0.0 0.0] min=[0.0 0.0] max=[1 1] step=[0.0001 0.0001] } - #endif - #if defined(DETAIL_TEXTURE_DIR) - float2 detail_dir; // exports = { name="Detail Texture scroll direction" type="vector2" value=[0.0 0.0] min=[-1 -1] max=[1 1] step=[0.0001 0.0001] } - float detail_speed; // exports = { name="Detail Texture scroll speed" type="scalar" value=0.5 min=0.0 max=10.0 step=0.0001 } - #endif - #if defined(DETAIL_TEXTURE) - float2 sample_tiling; // exports = { name="Detail Texture Tiling" type="vector2" value=[1.0 1.0] min=[0 0] max=[100 100] step=[0.0001 0.0001] } - float detail_offset; // exports = { name="Detail Texture color offset" type="scalar" value=0.0 min=-1 max=1 step=0.0001 } - #endif - #if defined(COLOR_TINT_MAP) - float2 color_tint_uv; // exports = { name="Color Tint UV" type="vector2" value=[0.5 0.5] min=[0.0 0.0] max=[1 1] step=[0.0001 0.0001] } - #endif - #if defined(DISTORTION) - float2 distortion_strength; // exports = { name = "Distortion strength" type = "vector2" value=[0.5 0.5] min=[0.0 0.0] max=[10 10] step=[0.0001 0.0001] } - float2 distortion_speed; // exports = { name = "Distortion speed" type = "vector2" value=[0.0 0.0] min=[-10.0 -10.0] max=[10.0 10.0] step=[0.0001 0.0001] } - float distortion_offset_top; // exports = { name="Distortion offset top" type="scalar" value=0.0 min=-0 max=1 step=0.0001 } - #endif - #if defined(DESATURATION) - float desaturation; // exports = { name="Desaturation Value" type="scalar" value=0.5 min=0.0 max=1.0 step=0.0001 } - #endif - CBUFFER_END - - DEFAULT_ROOT_SIGNATURE_ATTRIBUTE - PS_INPUT vs_main(VS_INPUT input) { - PS_INPUT o; - o.position = mul(input.position, world_view_proj); - o.color = decode_vertex_color(input.color); - #if defined(DIFFUSE_MAP_TWO) || defined(DIFFUSE_MAP_THREE) || defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - o.page = input.normal.z; - #endif - #if defined(UV0) - o.uv = input.uv; - #endif - return o; - } - - float4 sample_diffuse(float2 uv, float page) - { - #if !defined(DIFFUSE_MAP) && !defined(DIFFUSE_MAP_TWO) && !defined(DIFFUSE_MAP_THREE) && !defined(DIFFUSE_MAP_FOUR) && !defined(DIFFUSE_MAP_FIVE) && !defined(DIFFUSE_MAP_SIX) - return float4(0,0,0,0); - #endif - - - #if defined(DIFFUSE_MAP) || defined(DIFFUSE_MAP_TWO) || defined(DIFFUSE_MAP_THREE) || defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - [branch] - if( page == 0) - return TEX2D(diffuse_map, uv); - #endif - #if defined(DIFFUSE_MAP_TWO) || defined(DIFFUSE_MAP_THREE) || defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - else if( page == 1) - return TEX2D(diffuse_map_two, uv); - #endif - #if defined(DIFFUSE_MAP_THREE) || defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - else if( page == 2) - return TEX2D(diffuse_map_three, uv); - #endif - #if defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - else if( page == 3) - return TEX2D(diffuse_map_four, uv); - #endif - #if defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - else if( page == 4) - return TEX2D(diffuse_map_five, uv); - #endif - #if defined(DIFFUSE_MAP_SIX) - else - return TEX2D(diffuse_map_six, uv); - #endif - - return float4(0,0,0,0); - } - - DEFAULT_ROOT_SIGNATURE_ATTRIBUTE - float4 ps_main(PS_INPUT input) : SV_TARGET0 { - #if defined(WRITE_MASK) - #if defined(DIFFUSE_MAP) - float mask = TEX2D(diffuse_map, input.uv).a; - #if defined(COLOR_MASK) - mask *= input.color.a; - #endif - #else - float mask = input.color.a; - #endif - - #if defined(THRESHOLD_MASK) - mask = input.color.a > mask ? saturate((input.color.a - mask) / threshold_fade) : 0; - #endif - - #if defined(ADDITIVE_BLEND) - return float4(mask, 0, 0, mask); - #else - return float4(mask, 0, 0, 0); - #endif - #elif defined(DIVISION) - float intensity = 1.0; - intensity = pow(max(pow(((input.uv.x * 2.0) - 1.0),2.0), pow(((input.uv.y * 2.0) - 1.0),2.0)),2.0); - - float4 color = input.color; - color.rgb *= intensity; - color.a *= intensity; - return color; - #elif defined(CLEAR_MASK) - #if defined(CLEAR_WITH_ALPHA) - return float4(1,1,1,input.color.a); - #else - return float4(1,1,1,1); - #endif - #elif defined(CIRCULAR_GRADIENT) - float2 uv = input.uv; - float2 offset_uv = uv - float2(0.5,0.5); - float hypotenuse = sqrt(offset_uv.x * offset_uv.x + offset_uv.y * offset_uv.y); - return lerp(to_color, from_color, pow(hypotenuse * scale, exponent)); - #else - - float4 c = input.color; - #if defined(DIFFUSE_MAP) || defined(DIFFUSE_MAP_TWO) || defined(DIFFUSE_MAP_THREE) || defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - #if defined(DISTANCE_FIELD) - float smoothing = 1.0/smoothing_denominator; - #if defined(DIFFUSE_MAP_TWO) || defined(DIFFUSE_MAP_THREE) || defined(DIFFUSE_MAP_FOUR) || defined(DIFFUSE_MAP_FIVE) || defined(DIFFUSE_MAP_SIX) - float4 diffuse = sample_diffuse(input.uv, input.page); - #else - float4 diffuse = TEX2D(diffuse_map, input.uv); - #endif - float alpha = smoothstep(0.5 - smoothing, 0.5 + smoothing, diffuse.a); - - float dist_mask = diffuse.a; - if( dist_mask >= min_value.x && dist_mask <= max_value.y ) { - float factor = 1.0; - if( dist_mask <= min_value.y ) - factor = smoothstep(min_value.x, min_value.y, dist_mask); - else - factor = smoothstep(max_value.y, max_value.x, dist_mask); - - float3 color = lerp(diffuse.rgb * c.rgb, outline_color, factor); - c = float4(color, alpha * c.a); - } - else - c = saturate(float4(diffuse.rgb * c.rgb, alpha * c.a)); - #elif defined(DISTORTION) - half4 normal_distortion = TEX2D(distortion_map, input.uv + distortion_speed * time); - half2 distortion = (normal_distortion.xy * 2.0 - 1.0) * clamp(pow(input.uv.y,2) * distortion_offset_top, 0, 1); - float4 diffuse = TEX2D(diffuse_map, input.uv + distortion * distortion_strength); - c *= diffuse; - c.rgb *= length(float2(1.0,1.0) - distortion); - //c = float4(distortion, 1, 1); - #else - #if defined(ATLAS_COLOR_LOOKUP) - float atlas_index = floor((input.color.a * 255.0f) + 0.5f); - float2 atlas_uv = scale_uv_coat_of_arms( input.uv, atlas_index , atlas_tiles ); - float4 diffuse = TEX2D( diffuse_map, atlas_uv ); - c.a = 1.0f; - #else - float4 diffuse = TEX2D(diffuse_map, input.uv); - #endif - #if defined(ONE_BIT_ALPHA) - one_bit_alpha_mask(diffuse.a, 0.5); - c.rgb * diffuse.rgb; - #else - c *= diffuse; - #endif - - #if defined(GAMMA_CORRECTED) - c.rgb = pow(c.rgb, 2.2/gamma); - #endif - #endif - #endif - - #if defined(COLOR_TINT_MAP) - float3 tint_color = TEX2D(color_tint_map, color_tint_uv).rgb; - c.rgb *= tint_color; - #endif - - #if defined(DETAIL_TEXTURE) - float2 sample_uv = (input.position.xy / back_buffer_size) * sample_tiling; - #if defined(DETAIL_TEXTURE_DIR) - float detail_value = TEX2D(detail_texture, sample_uv + detail_dir * detail_speed * time).r; - #else - float detail_value = TEX2D(detail_texture, sample_uv).r; - #endif - #if defined(MASK_WITH_DETAIL_TEXTURE) - c.rgba += detail_offset + (detail_value - 0.5); - #else - c.rgb += detail_offset + (detail_value - 0.5); - #endif - #endif - - #if defined(PATTERN_TINTING) - //float4 pattern_sample_uv = float4( scale_material_uv( input.uv, pattern_variation ), 0.0f, 0.0f ); - float4 pattern_sample_uv = float4( input.uv, 0.0f, 0.0f ); - float pattern_value = TEX2D( material_map, pattern_sample_uv ).a; - - float4 armour_tint_sample_uv = float4( pattern_value, (atlas_variation / 32.0f), 0.0f, 0.0f); - half4 armour_tint_color = TEX2D( color_atlas, armour_tint_sample_uv ); - - c.rgb *= armour_tint_color.rgb * 2; - if( use_grayscale ) - c.rgb = (c.r + c.g + c.b) / 3; - #endif - - #if defined(CIRCULAR_MASK) - float2 uv = input.uv; - #if defined(UV_SCALE) - uv = fmod(input.uv, uv_scale) * floor((1.0/uv_scale) + 0.5); - #endif - float2 offset_uv = uv - float2(0.5,0.5); - float hypotenuse_squared = offset_uv.x * offset_uv.x + offset_uv.y * offset_uv.y; - float radial_threshold_squared = (radial_threshold * radial_threshold); - float fade_threshold_squared = (fade_threshold*fade_threshold); - if( hypotenuse_squared > radial_threshold_squared) - { - float diff = hypotenuse_squared - radial_threshold_squared; - c.a *= lerp(1.0,0.0, diff/fade_threshold_squared); - } - #endif - - #if defined(MASKED) - float2 masked_uv = input.position.xy / back_buffer_size; - half mask = TEX2D(overlay_mask, masked_uv).r; - c.a *= mask; - #endif - - #if defined(RADIAL_DISSOLVE) - float value = sqrt( pow((input.uv.x * 2.0) - 1.0,2.0) + pow((input.uv.y * 2.0) - 1.0,2.0) ); - if( value < 0.9 ) - c.a *= lerp( 1.0, 0.0, (0.9 - value)/0.4); - #endif - - #if defined(GRADIENT) - float4 gradient_value = TEX2D(gradient_map, input.uv); - if( gradient_value.r > gradient_threshold) - discard; - #endif - - #if defined(GRAYSCALE) - float intensity = (c.r + c.g + c.b) / 3.0f; - c.rgb = intensity; - #endif - - #if defined(DESATURATION) - float intensity = (c.r + c.g + c.b) / 3.0f; - c.rgb = lerp(c.rgb, float3(intensity, intensity, intensity), desaturation); - #endif - - return c; - #endif - } - """ - } -} - -shaders = { - gui_gradient = { - editor_options = [ - { - name="Pixel Modifiers" - options = [ - { name="Diffuse Map" define="DIFFUSE_MAP" condition="!DIFFUSE_MAP_TWO && !DIFFUSE_MAP_THREE && !DIFFUSE_MAP_FOUR && !DIFFUSE_MAP_FIVE && !DIFFUSE_MAP_SIX" } - { name="Gradient Map" define="GRADIENT" } - { name="One Bit Alpha" define="ONE_BIT_ALPHA" } - { name="Grayscale" define="GRAYSCALE" } - { name="Atlas lookup from alpha" define="ATLAS_COLOR_LOOKUP" } - { name="- Anisotropic Filtering" defined="ANISOTROPIC" } - { name="Circular Gradient" define="CIRCULAR_GRADIENT" } - { name="Distance Field" define="DISTANCE_FIELD" } - { name="Detail Texture" define="DETAIL_TEXTURE" } - { name="Detail Texture scroll direction" define="DETAIL_TEXTURE_DIR" condition="DETAIL_TEXTURE"} - { name="Mask with Detail Texture" define="MASK_WITH_DETAIL_TEXTURE" condition="DETAIL_TEXTURE"} - { name="Tint Color Map" define="COLOR_TINT_MAP" } - { name="Gamma Correction" define="GAMMA_CORRECTED" } - { name="Normal Map Distortion" define="DISTORTION" } - { name="Desaturation" define="DESATURATION" } - { name="Two Font Maps" define="DIFFUSE_MAP_TWO" condition="DISTANCE_FIELD && !DIFFUSE_MAP && !DIFFUSE_MAP_THREE && !DIFFUSE_MAP_FOUR && !DIFFUSE_MAP_FIVE && !DIFFUSE_MAP_SIX" } - { name="Three Font Maps" define="DIFFUSE_MAP_THREE" condition="DISTANCE_FIELD && !DIFFUSE_MAP && !DIFFUSE_MAP_TWO && !DIFFUSE_MAP_FOUR && !DIFFUSE_MAP_FIVE && !DIFFUSE_MAP_SIX" } - { name="Four Font Maps" define="DIFFUSE_MAP_FOUR" condition="DISTANCE_FIELD && !DIFFUSE_MAP && !DIFFUSE_MAP_THREE && !DIFFUSE_MAP_TWO && !DIFFUSE_MAP_FIVE && !DIFFUSE_MAP_SIX" } - { name="Five Font Maps" define="DIFFUSE_MAP_FIVE" condition="DISTANCE_FIELD && !DIFFUSE_MAP && !DIFFUSE_MAP_THREE && !DIFFUSE_MAP_FOUR && !DIFFUSE_MAP_TWO && !DIFFUSE_MAP_SIX" } - { name="Six Font Maps" define="DIFFUSE_MAP_SIX" condition="DISTANCE_FIELD && !DIFFUSE_MAP && !DIFFUSE_MAP_THREE && !DIFFUSE_MAP_FOUR && !DIFFUSE_MAP_FIVE && !DIFFUSE_MAP_TWO" } - ] - } - { - name="Masking" - options = [ - { name="Write Transparency Mask" define="WRITE_MASK" condition="!MASKED"} - { name=" - Additive Blend" define="ADDITIVE_BLEND" condition="WRITE_MASK"} - { name="Diffuse and Color Mask" define="COLOR_MASK" condition="WRITE_MASK && DIFFUSE_MAP"} - { name="Threshold Mask" define="THRESHOLD_MASK" } - { name="Transparency Masked" define="MASKED" condition="!WRITE_MASK && !CLEAR_MASK"} - { name="Circular Mask" defined="CIRCULAR_MASK" } - { name="- UV Scale" defined="UV_SCALE" } - ] - } - { - name="Depth Testing" - options = [ - { name="Depth Testing Enabled" define="DEPTH_TEST_ENABLED" } - ] - } - ] - - contexts = { - default = { - passes = [ - { - defined = "OES2" - pass = [ - { layer="transparent" hlsl_shader="mobile_gui" render_states="gui_gradient" } - ] - fail = [ - { - defined = "CLEAR_MASK" - pass = [ - { layer="transparent_mask" hlsl_shader="gui_gradient" render_states="gui_gradient" } - ] - fail = [ - { - defined = "WRITE_MASK" - pass = [ - { layer="transparent_mask" hlsl_shader="gui_gradient" render_states="gui_gradient" } - ] - fail = [ - { layer="transparent" hlsl_shader="gui_gradient" render_states="gui_gradient" } - ] - } - ] - } - ] - } - ] - } - } - - compile = { - default = [ - { defines="" platforms = "D3D11 D3D12 GL2 GNM"} - ] - } - } - -} - -static_compile = [ - { shader = "gui_gradient" defines = "MASKED" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP ANISOTROPIC CIRCULAR_MASK MASKED " } - { shader = "gui_gradient" defines = "ATLAS_COLOR_LOOKUP DIFFUSE_MAP" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP CIRCULAR_MASK UV_SCALE" } - { shader = "gui_gradient" defines = "WRITE_MASK CLEAR_WITH_ALPHA" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP PATTERN_TINTING" } - { shader = "gui_gradient" defines = "ATLAS_COLOR_LOOKUP DIFFUSE_MAP MASKED ANISOTROPIC" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP MASKED" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP MATERIAL_TINT_RGB_1 MATERIAL_TINT_RGB_2 MATERIAL_TINT_RGB_3" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP MASKED CIRCULAR_MASK UV_SCALE" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP PATTERN_TINTING MASKED" } - { shader = "gui_gradient" defines = "DIVISION" } - { shader = "gui_gradient" defines = "WRITE_MASK" } - { shader = "gui_gradient" defines = "ATLAS_COLOR_LOOKUP DIFFUSE_MAP ANISOTROPIC" } - { shader = "gui_gradient" defines = "ATLAS_COLOR_LOOKUP DIFFUSE_MAP MASKED" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP MASKED GRAYSCALE" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP WRITE_MASK" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP GRAYSCALE" } - { shader = "gui_gradient" defines = "CLEAR_MASK" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP GRADIENT" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP DISTANCE_FIELD" } - { shader = "gui_gradient" defines = "DIFFUSE_MAP DISTORTION" } -] From 330ef33cbdbf50d1a075cecfd2310d24a22591fa Mon Sep 17 00:00:00 2001 From: ManuelBlanc Date: Thu, 14 Feb 2019 18:28:01 +0100 Subject: [PATCH 2/2] Add latest (342) physx_metadata files --- .../physx_342_win32.physx_metadata | Bin 0 -> 52281 bytes .../physx_342_win32_64bit.physx_metadata | Bin 0 -> 49053 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 vmf/core/physx_metadata/physx_342_win32.physx_metadata create mode 100644 vmf/core/physx_metadata/physx_342_win32_64bit.physx_metadata diff --git a/vmf/core/physx_metadata/physx_342_win32.physx_metadata b/vmf/core/physx_metadata/physx_342_win32.physx_metadata new file mode 100644 index 0000000000000000000000000000000000000000..7097c7dcae2d338a376aba883fbf970003e87a01 GIT binary patch literal 52281 zcmd6w3z%F-b>~~M0UHdA!48HcxCcZmW8sWt#R$aU(ef>YO@t>T&DVy(90~JU3BVdG=YQ5YFbf=cX&ymN|Z07lfzz z!_aR)rDvXjKNo)Ckfgsb`G0o?J_^62K>o5b@GIc!3*=t|dxD@W=SBHegmcMn4(GDj z(nC^7d@E5bk8g*alfz#}x|Kh|xdkidsV-mocM?_iEc@q3|8BPL`pCYEIJaQ_Q~TCJ zqUvbrmQTD%6wBg^q+9)8%((^ABmcZHB&z)^-SSEQtwgab{ck4S^snOFg6Wa`9U(DG zUi=-zJp09efhgZ($^U24vx549!mkp|KFM1!`$kE4FeJwPNBvzv{G&v%m~-iZ%728Y z{L-nI4xb_6T%snaWTIN>b4kDKGyOJ(Mo_5pFA-ITbWnbUzam=w%x0yV9j7_}2PF_< z`z^2Lw|@&vCYci6B=H$JT;@EBHjUsFITiwA)Icon) zL!nviukn8wTr931moB{W4EiO%CFswR7oUcU*`B3;l=N4_ zFDT%zg=_xHl9&FyaQQZmSK;LX-iNO$;J3n87x1^k*A(z~!p92uJ@9n}{J+817x3SL zU!B7>zdQmThiCO4jlD0xXE<_5`VFTpsC~W$P(RG_?-Q`B@ji*; zE|yik_-gpF@u|!NaVuXsOpofL`mRA%bw~&0QL>mEphGg2 zZuvC+HNM5vN7MWkWPgHKhQ;#cANB8_hObI-E?toQcN5h=r8})(nSL35DMt>;yy%?G z^#@7(ZDP9rTKT&FeF{EC-Yorp29uA{L3L61dInRv@pCva|EiB$uzEaM|EhfXr;Oq( z`&FL&Gs;n>D!LH**UPYPEpZiz91{PUe_l)C6jA=q;_9Ef0D1n^_^H9=U+J`ZbLv7H zCLg7PCEd=6`EON}$@HAbf4_+Q{Y3uDv|s)2L7;3?9@ERI3*w&y6wUvS!ZjAN^zfy zuR>lr(!q3XiS(Pz%KPo=m;bLvhx93$9H%bqhpCKou=0CR`D#N8rsqucJ5%}MZ=sC5 z{&OcxHl%~u_sfxe>O&U3UHi1YdH@~Lr}~+k>3JBYGSb1y|HG*KtobR;6aC>tTy3x{ zL|lC&k+X~umyg19WHb?we$^qFw=72_uQ}T4W7rCmyyh4V!y%H_7}5QAC@$TT*}4NKIwX#3p4$iBP^I6$-gidXLF3@(NXhn87?LtnjEJ|xCH(@ zuEetV82tG;T=!42Z=5_9Opo?AHU#@LM_Ib%Q~w-?i)Hms)qk3}8Xo)4=8C{U>jJ6aN#q+BTNw(gpeF z%S7wDW_Q#)rN`jv`?0+7Z^Eqpy2n{CJ@U^pwfR8E>VKz6AAyTy>6e`JoBw5}f{u0` za|a`4?Qi}unOOdX!9J7KaRg&5uk@S$ERV65AuF!*+YEBFc|=@$1PU=X|A^}uU-o5j zjql6Jqw>ayCda7@qx`Oi&v3-#WnArZHGD3`t^G8Ay$-%N#kq9h&HP>qzk%Z_V!Hh6 zU<<+Ml!V?eH_{f3kcAV^n_& zv3+^{OZjd5sC{hwD1D45A838A`f*yS>LU*gukVs7muZv88ZtN$$0ekzNs%i34` zjqvpNC)owH-%r8w#_wtPU2xSc)^E*c_op&EYknZP^h?OE=a?n0{`&#=)hW(p68<}U zoGban{9;h^?{C8=IcDis{XYZWR=~dupUUB?|NnyLjX!a1&Zfto`A6kHp9_t@Ec+z? zQuw|cZsW_^XC&mC;iz-fU;S&GqkLoSJTt!XjGXL+^5U{TQ~y4%zlfhnUR*)?t$!r; zlOEU4+BeOud~4r4ZteS>aM@=1v*g8X{#1KpweJ{htNJN#M?WE~2uJn*4dhW!eWfD~ z;;)5^-Ih0o-0`DZVDUk<+!X7yJd3s!%<|C}d}g6e1KE`cBM z7F;ZkAA^?*_>aTKa=7gOkMMDhar<%Ug7_)8^}n=z;_ruVR*o%^X4Dxf2RKgdKBc#6U5IVYwh!Ct}WR8NnH0Jg_v7C)V_a1?7;UCEuB*r z9*^{E4zpnSMoG~6S0T%Pn*Y9u4zZY%gMPLDgXB@j(y#l* z!|*))e-i1}8pDFwsrLV$L4VwTtbJwQV?;64-{ee>>h}$Jx_=m#|IWg>>ib#xoqyoz z^_9u1{ujW@9JA^#{(bN@Ib8eiuZGJ{oG!CpT<_OkP1KmTaql_<*Vg`4KkEZJDsDr! z^^XU*wqSb1ZT^V4Y*EnsApci6myax6OhN6p7ahkrSNo-TB`RP3wP5+wzZc1)kk!AB z!`?zPW^!JFa$$E7RUfe|Zh7OQ*>WGU8iVOz{6p~3H00X&AH&VR<551d<9gC;{AKx1 zy1#-BG3hipPF)cHDm<_MY5nmyyv#96Ui=&IRR#R4XD#1uZLS3bD9MC|4QW5x8m|G!v=esPf_SgKWu{KULIZj0bhXMki(_F2j7>& zZGBu#acf^2zhi==L zSjO@=K@bHLl}V;Y@S6{OfSKK`uWR!^x7#UkEFzpSXOWkX8RnBKa|&&HY+E z#HB+ai(duXL{wXri6+OX3*u&9Ii%@e`SktW_Ml&Ll%*?=!W>NNV`FKqJT>xsFGsO7 z*VyjEU&1kKet0X)>^nss3#Lb0bx=6ve*KSe*?%{@%+YN0IsC82-+l0_IcD`A-QPa~ zALpoIOfRP{Nd6JP6vsUI&%kHkdGdb+xFJVg`o9I=SHPeDY=8gGDqr%Kz%{q!@gIOU za=7Y03GZ;svws$TJV##T-vmEVzz@T3E8r*Kw-@k}@V6E4yWuBu_$cY`hu>MiKMubu zhpYd74t_Vsto|$hm+*Jx@Y68$;dD@2DQJ9U1>@gD-p0p6QAX>h;x<2Iag}fL!ztuV z&QzWIoKop~i1(AAGL75(y9y>Bri0nH9$s|+-Uc`O%aIZ*NBu|Ne<{S}`xL+a(Dz?r zd0gL@$=)n3`?Nlhn^laJ%V`pJk%#{r%i?vQ>L`|QDI*+)9Vd=(9+z+a8zudA_ysA> zr3>$bnSZ3if|Vord^>-Q^SdVl>#@Ku~^jhNi$uS6Ke;sJ{j}LHCj^uTJSIF{@bT9EEHpF#7(Ea1BaFwS%l(t{|F1YHR#qWcC zgqUuB8$X|feSug;KCZvwq zQEiasSCDo+Tzc~SukWAt7V!PZ-%!BY@O=gRN8r^0eiFV=z<&weDB!;e?-cM4!}~d0 z`)~gPz66)=(*7f<^kw+59DW7qe+NI#G0(sHIO#+Ie;)j{0zL}Ay?}o|{B1d0_1g|V z3D2sZ?B5N)Ge=&$0>7((H{f>{@MG{(1^g%A_ZILw;qT7j_rPp?-%lP3){Y;97maU? zUmM>Vzb0pT9*Oj8j99RIqa=KVJPKLuf132i;bJjAM*;-NKLOWu%*7PMpUuZ>8rwrW zC~)#Pz~m*PFyasH{maG3>pGT?%fAeML5c@)SN^Nu7o~Zse3Li1xcsfiYi`Rc|Ml>4 ziklwQ?+|=dnuqe$Kh^%_z&W@Om;XlOSCg7o{z>?n6!%)Z|Nj$wEX`B(H+hqb%l`oK z>r(PT-1+wt@bxKfdQ|@}z^_j8RQV=va&h_pfc$t$J}&>6G~Q&2n;w;aF??H^2L)>-~9u$bH{Y~EFto$~z;!5W<2`j?cX^yuBkkvoL ze+Dj=$A1|vbF#SXdjP&{{F1I9{=0D58_PR|fy;iAC&>k?U)KC2J!2u?m(XqXpR-EC z>{RXdHS!eA-{)RfJb$l(-;16h`$PHC|AX*%7w~K0@5|v@-!$O&bCeIvZcbegzXkpv z$1JY$Z-sx7W1f9?z#qxs(ti*9(;Tz(i~kDz3kCc`@V_qLzXShz0skCa70)VP^?M9{ z9z3sp--3@6@aKIGW21my3co0aFH-&l{KfDWdo%eR1lhL(zCK4@{6_fIIb8m|89olr ztN#*wDo0-W-vXb>;iut02Um#wr}3;XO8hTyv6zb~h(8Ed{vjR|ypD8@Ka=Oug^_Sn z`Hv#6y2bKw`Co)9f6RlpEB`S#LwJ}61+q`&o4m=zAwVC z<~U?uP@wix`RW_u7UJ?>i~K4;EFYJ@2fjMRO^?cN!`GyFP+Qu1;6 z_rTYsxam>(AB5ZecZGqVKwR}VdBbt}k0O6HAg}&^4IfW&)8q8RC(}Gtf0H-4xcnE< z_}fzQas6KjpGtAlqw>e$GijcxzsZ|iT>c*9=Th=<`G?_qQ{42Z{GWv1kmf;wzQ30L zP2S|<^528}zLb1i{)6ypiklvl|0(!Fng<2e|4iQG;`09z`9?}UF8{0-=0D%6{4%_s zlDGAPmEQ@Rg9~x_6UZ--n%Dn+7=Ap(y%s%zYo5xfIk4AD&U`h&lK>_ z!qf8;*%R0(Q3$FIEJjQgC{BgM1mL>l-xa`l8m;O_5hFK=R zp7dXXtN$pb^~?VsC91t+{no$a-$&u=a`=}>|8uy;r`3VeBv|`e{Z$VI9TlZt{xw<4 zHxu}2besQgC(VM@L)_-CEUxx@28}EIS@k>9`!So}%E+6IW`mBh{{`q@!!gz`rl5a+ z<>l}(&i4|{ZZQSxUy`46DPE8A%Rg(89S!O6L1ih7!_7ak&w`cnL-1Whh1fp%SwXsQ zfQ!XkOyOo&hiL6$dQJWfu%hzCWuroteLsE%d2#8;lYeIOSi1|NBZ@QYr#&%O@9{G_Yofo`X55rbB}fWPA? z|E1-{AA|pM4p;wN$;VNeXR_LN6#fGEIR*SOc;55>)i7)SQ|Pi_c8Xj3pEAhNxZZDX zC6D}nGD^3s(~5}9{FxOlH=3``R``<6vsUO9)oM_W^uj0eha(` z&$_?817`lw9BIMoFK+f{alK!>k31@S7188OkG1a@30du{d}?3K-;zzs|9WKKgUTF& z%i^lv6kPt2PSeY&3wvNzKee9)%O`I2%i_BK9wLuyzny4ursoZ?pCR5! zLY951|9gpd!KEWDFaBZTy*d05nAvZAf~-S&?B8FK?zDd8{Y*&Ln$FgBZZLDLZ@WKB z8F~KwQdIsJ`7KyEvhQ)CLYXK%ad7>Q%w-ZKqZkK1Uvl=1a?G+%`t|+zD!6o;y!k?M z|3aSCDbA$};!nWWaE#?WWo*Ob-!ci(ZTV)TkZ|tB#r~K5=aWYv)^GO7e=mTGW${ZQ z{o_&+g0+*leSbf0kfZrQT;JcTZ)Ne*q^~89?8z!$-w*yEybM<~y_~wR8D{-&Jc4GQ zcw%3~?NnSoboN;yn(g#V_RS$XPt^Kf(d3+Q{EQM0!}Ho->z5_C`mWY5X?g44BXH$W zke^(Bj%wc@MLr!)hJ-i6%s-tdlle#7{1bDtL)`q6#ZRNNsQsR-f3$x58EhD%oN=Pr z#i05La39my!M``X5elE?qcN|N1Jj=AYvx#L@gCZvKh6*{S;dBQbCM zi+_u#@tI}6)}LBmj=&d)rk7I}G`~N+od5lg_;caM$Ss@AZoB`KVOGBe+=As3xBA5# zwJw~geYO6y^`+LICKtp@-(RMEiIXI7SjMj-@c^+3%kq!4zkHL&i{_8R=(hTIBIB(7 z;#U8dTUPO8{;))BvC}j8=gH0=XPRHj*moOo9D}m_^H$iqh?6;7^?M(2TMk$I{Tfm4 zFF7Rj=G28JJAcVOYoAAgP93a$#I1c|jyW#q`9jYR8h;NGE!|V@U1eXthe^otkN88x zPv&sd-|XWw3098eZGAQZRT&DhN5R%-Vv;dAF$MK+tsl=Ps?Jt#8^6-8^;zEhIf{(d zXL|mK>&K-F;#!|^8_ML;ulkvNmT&KBCtgzjwff5j3s#T6BHHMtX7?aJs`^1av z6Mri0)88+cee%Br^Itczf5srk72#a_kH^U~!f`z@G)thgJsD5H6_m&1TmnCLzyh`; zcQjk>0h)c1w_tj-f2Du_T0t_F?h^PB*Z1RMdHjCLP=Cwfvd{khDvN&@ZuY4USTH+O zzW%;TAxmET578l($5p>P`>cNF707=X{qkLw{;x&$Ykss~_KT~I3Rzs`pY_t^_a`U7 zkN7j;8n;>HpAR$tC1absR=&8EpT(trRYCc$i1cUKFK+s?xb#mH=ojA#&#T{#Gn6m> zRF+?h%2yw;VB=fd=AW3G|4$=OG`}~IX9`&s)Yb}bipoFfliaWA7uOu4kj3TSJIOP{ zF{}TG{~~;@fPVnKH;2prA0^%ZSNoe?oVpRwEZuF+4z!=ELi)Cs}Cr|-1La+9-+RG#qIfQ1Rndx?%%pUtVYKL z9M=U69zdN*ZiseCHwOF*HLsd;Boy;mHOYC;GF_~2fSav)xYxkud6@u>c46mvzt>F z-T|}v$L)Vs#EbfmI=Qkt&sSPcdpT({JWO23s?~zCL z<@Jxxz|}T+{LkTe^PluttM;+> z`%e1LzfwP@h-E=K6wX^U@ZU-6G^E?9xb>ebF8vpgNA_Jr)V~842d%FzhA)sPZh9?` z=C8}(caxAcf9d{t75qdFzX$mV_yh2L#B}+(KWv5T`~58auYvD^uY>Cz#9=6i*Wu$i zd=&npaP426&3Rg0{LS#00)7Wv-?nARYy7+ezPEtC3w}cZzYo5zfPVm9E#M!9>;E%# zc1HbV-^1`m0sj=dQ@}qD?-%gDgfA8F$Kl5dxb9CU3b@ukx8?9B&~5XJ<~R#yg%fd` zUt*3r7sPFT$>RUN*EiZfe8$WD{4Sf#?qI&#U%UvuE3hoC{l(qHl_7FS7GgHPXnwHy z<802yh$F-^t)DKX?4tYMYvI;DC(viX>=d{8>x4m$#`S#mQKIb2njh4^)qjfCPwGD% z@~K{?ms1y<{mhYCKdmID`Oe7xto4t$^{<$l9&zhmS^Q~~srTFRb!?xlZ=dS*v$c=> zdxEI&owR=?^3Oge?SHKP;?}-d+}cm&$MrW=;%YznE{k`f@?-zn_!lo~AMx+z_A&p; zKl_LZ-%0ztf%?6Tm=4mR@YAqSe>(JQ{9d??U+a^~XzeT6-w67%+DG?|kHE#U#@ELp z{Tc%nOuy{^lb~PaTe{^l{bE`AKldc{%Ri41r9Z2F{}}1l`ox0Sd76ahexFZ`<;|C) zpclf$V(uk;`xKS`5@fA?vdWkKtny9&lP&*MQTh8!DMzcn#_x_$|8dUaHs;dZzxKh! zBx7=%x}f`C3qHYB9{&;e#vDFM`cJ_pIcE7+{O94@a=7fj4?b1Ee+{njnWbOy55x23 zFO~lpxYi!lhdE8|&tHI9`>HQlu=!2=Z;1*qm#-AmKL1KQ$@xB_rE}`Sxt9#|k69u| z%P0Fs$)k{0zboKkd3+N*Z~RFAEL?pzPyR;uNCB_IFDT$g;TIL~x5Krz$SeOIc)5W8 z27FZxA0=JwyP9KG`+gi*Yu`NopXvW^^;vYt_B{Lb|9>g+{}+)j^8Z)hMgD&rUgZB3 zRKCdn7s8ADe=)pVP`^vzdHz@bx(d#Jx&Bf6tVwg-ObFu$TKkN<6#o;CkDXFZ$n*b= z@S^rvfS*$!e+Rs%eclIG`^d*nC&oejPv5VSCD*=>0+-c4D3SmE7OuXTSHI_6y8Q2Z zg1CGCBmb@^;T&RcYjSc0vgY6WZBiqj`B(GPcJe4ZM3fD2(D>O6e~3iIG*|omF#LoR z64PA!2Q_gFvpSNL1o2zp_ZRSAfPblge-J)G-Lmw{zrP0`hpP?K_KANUK9j@s_eXyZ z-v=MhkSD41P53Febf@*Jf2e)#g{zNo@PYa$JnI#M_9?p*|6}bV`z|4mf^=KDOW;R* z1Ki5a;=ADL8+q~z@S^^IE8KjS)<23~)lc(NR{c&QYyD3;ESMh2zlS^uS@wzlS9nqV zeiNQoKeKOH{eu4=j_jLpR`?&YPwn%kM1?ZZ(siw%@%1>o%z13T>`@pcuHYleRUBh3 zrXYSEoMDv7<-Zrh*Q9u?{}u4D6z9?f>Hk6aI*xheUklg#k;T=&4#BU^;nM#T@bLnE zFMP6qe+<5@fUAE^rFm#So8QWTuL?(NOY48;Kl79E&r`Pb&rh#FI0QRY{l7*Yg%P5B z6bJDq;9`0FLJBVz@K?ac3ixLDcn&AIbR&Ep$9)*B7zf#R1U|zt%f26j{VeezO5Da72es(yMut#(oUEZqt4qxakT zzB|3YZv9u!ZjY*d2ug>^8y_W2^NaS^l@_LzOzc3;Z-k`A2E7{NDe^-27+ur^|n;cs#!1`kVjM|E>R= z3_j7p#-F%-pA>UzN3D-uANq%MTDqxH|6CxdzU2&l6sEsVS%S$vlb1gfMu|U8p5q*2 zE@t6p;U~C|tjQbGQO{p*3@nTPI`VIVKPN;E$@u;-%=}|M6E;1%fBZgq6vl}oI*Gz4 z=bwd-bIh_|T>XENqxy#V-6op9Kvp)SgLEle_5I#Q{%Y`Rd@tPW?+kEazjQaqqmb2p zs-N~J#Io!cKZd;K`8@t+xY|FDza4%<0e?4qUjhFEc(s6Q|6!qk{}b|!9RBpNf&WgD z$3ooxFC>q`31XQT2l;0deu86G{nh@jgx{9KCI2e;?FC%@=WS^oZd99)we}w&kA>L& zJ>*fyvQPc10vF5TvcC=2c+KJ@yZ&wSp7OX5?7J0NvoGnCWQgs%E7*5}^fECH^3N~A zPjFN$6XWpyNdHJEQ{41xd^{ZVccOIDq4s}-D0VV~%fEj_l){k=uKN8caYO|Ytz52L z_zKMGUk+(HSU%OyJ;Za!@~`*^KVo_OvZhBDL~b1v?ct{V_K^s=Mh|9WCATjB@hqwfvwktNp~)KhB1$4XoS}x)ffB ztkwUNOYuLJPu$+m#N6z_{L(APbCP3RzWRfL_^aS|a?InK;dkY5v;XcCH~Xbu_FMUD zLcSS}Bg7&O{=depesTG+{->Io|MJRzs`xBzXZ=V1wqX53?bjxcLfrm7#jm}71TL1v z)qZ!t^X3=pAL`p#@~0yE%AwDzY_m_?=9et4`q})V`k9<`C_E79kH@c#AMv8`t@3Sr ztNgTn&Fd>mFXIXQEcgF1KHL2tNmrEg|5bc?N&kAnGfMh50?u)NDSvKB|K7thOJC*p zIqq){pIa)IH4+Z!p6&kD>#P;}qU7uq`fl}U zEA(~Q$`$$sXvGSBNncu_@1a+$)U0^cO3huRm6{<|u2emLhd8seYkg^cq0;4S`+8ko zaaF0e(C+q?z&R;bt}WGD?wYfirJc1(qjaFrt|)1DZT?CgW{#C^@fYh#M>)B6(ZP-F z#a6Xpxtej4ztvlS=v$QUwLI|zTH@Cw#LHoif~+8 znrJlI^Ob(PTbf;{RNF^4*84juol?{N>}hwan<%JXY7X)>XDZcdy>+k@vd;9obCvy# zTIoo;UM)3eL0mMw-2QgEQEFauwAI^DYqq<`O3jUn2M*M_yLz=Mw#_suty-zYl6z)p zQ@hpccPqGKd+W%KO0PFNUqMl$-l|o)W2H*#;9^53KH&;WxB}6Qm0oR2qjIpv`P{Ki zEhNc^)_k|tuerqLAluH`0cW4HyJ=U5?Wpw@e7QYWdbi!L^y}?bX{Ntn!%U^yug^DX zv&VY<8gA%Tn&|G9y0u>4*krxeue9cCr9-uDtJc_Asn!>JI~E)LdZ$q*?~!_MzTK<$ zkCl3h-2;{R+FY&GQvnAm)!O#fT)kPN1E?yU%KV{Pf3|*0Z6H3?KDgEuSMM)6v#Q5h zm1cc@OSeAnt|=T7lS^4PsRAgkT4{FFY`uQ{z=2k+*HfR_(Uw?ZwDMnb;6Sg|r-QWm zm3h1BblW%AToJy>I>8lm*y?1ZU-8~=wd=i_b1XHb-_^SHN@IJgTA#1=X8Ya6`98hf zU6opk%>byVntyApjW@f;)KnWbY=)Ca`yHvdMltLQ@_ltVEj2^)50EMnbhrvvx(Dm6 zQj>P}swiE(c}ut5^a);c+hU`kij@}Z5%PmAsc-*N?=l2yF7s+E%L{Tn^Mq=Y-}eTu%zspm-@9r0 zvy1zy^&`qX%dF9mU~)3Of1-MGu-FUM#Yto~YxO-zEb<2W-`#%h=blqP*lLou6b;j6 zGU6ze+k{opi+UGqZ>b)Y($+wTS}dNx92nCCbtZr<0PjQvT_5RtXJr6 ztR|Xv=EiN8enbhntI)cO&7JKww=UmP7MoMGBee#un&Yn5m~L0quI@Z!@dsz8`B1(u zHC<9^w!PS$cN3iVHqz7k$tW#hYU;7f8ChEOv} z@q>bDDa#ehvM6OJ%i3jGloGOR+$}XTy31BS`I8Y7R+H?+@M!hwTWfB-49MmnPfPt{pg#lt5C2`<+W-b<_ivmUb>p!h^Q_a1u+&3acM?OOCR-`fzXP zg|%d_#Kly-S=ZX3;ZIuoH@S6Zuha|kNPnR|f5@#q{C!!|)Z7B=j)iukTGF!BEpKhm zxs_#@6nzb68DcbpCd)9VGeScZNNrc^2afr*=giWCCJ3w2WShaHrP^mt=!p>m{d zWj9krtGu1{gLT%{l&7m%w`_BlGfTYzV*yK!{q5?pwXDT)5RV8F+(?SAS95!{udB7r zo>H&fI8y6wXU1~NR_BObSOK6}IR`4e$ozbDqIyJ*alNn3WX8K zYi+DodbaLP5bdai;?7!!C!0Z2A~E5Y?3Q!(u+&Vs^?a1(OPUO;)3D69%Q|bfZjXhr zpZLS2zZ+<{xT3c=JBy88t<-DOYMp@v2bfN8i8|NO%AsU&>ix7QN@2n2SFTkzsHqY6 z_ny|Na@tT@y|<;(>+fhE(Q+CG9kMPq@UI#*aW?%(4P5gxz|fVJk4E2Qv4p=hoazyn5~n=XU1D(ah48dIRLFIm#2>SV_NExZkzz z_e%O%kA+bOf6@QAMTRHJgJF>lcR2LH_}o3~*@RPN?d~7@EXA#F2CAFaF4nroB7-#O zc+Qja<5X2SEKc0YyXT)2efe~QaP7>s2h_omzB$p+(^qv%oBI<(*I&)GyN4IUNGh|c3IyX(EhO2gfKqf<47za{(8v9VjL z95Q45Ac~Wi`tV1GT1UNm-~>%ulgF6SwB`%GbdITq_12wYH zdQX=bC7)-C(BC2j%;$|pT{~@qt;MFFZ6~{xgWMGS zJnJt!uvLe#+Ranp>~F3mmlRyCO%o2o;+mZP2rm}+^n2#Y)IUAmpjL6Z*>LW>U) zk_K5?v;Ss4$(?2b_g3)?w-tXu&!^$Qeiz| zn|o~gXoDe)Dz^=!YYfn?sWxqV2H%^LOSG_$9`U4;4Q?y0R5mD*<$=3#AbFs!mow2j z6u)w>bm}}n@meb)rH(E7s^QJW5qk=av-zgtX~Ui{cCcEtNvqV{R_V#XzRuK%oyvOE z_)e|XQfYqApy?j7Z4=1yhkZ--s!XG$SPs1|Q^VP{e?{c)!94r5sui{r!vmn@@lUZ+ zQ(T7^Nwf3&bt4XYEnM*s$%+cioXyVHcvsd82eoOp&1#beE1t%7t$zim&vQeQ_iA+&1Su&_k>C62m@0cwJX>I}TwFB1z*eIk@R~kFbH)I=DP> z=w@X(xA)vVO$&KfpilQ5!`E0(pqS?lE`?f$S;;-1CFiCxJTuv4c*1LL?6wcpTGAXm z6FnJm=Z~*kF>#7p7?+y<;Hm8h;rC>Bh~;j4k)*S|r2Q#2&GlGGM@%LcHnDu2G`^{h zJGct$>Qre}^3tjN!k2dvJxg^$)`xsQqwvu4!}WB>61FrJ>s5P8r`^^{G722>!zeD6 zxrM1jPs*W0nzJCDy5qX)q<_ze9j-U*sI=I$<|%#niuqV?Ph20SZ>VPldF$$Nzn|{7T^*)V zr^R=?PykKqvIfJ$Ve`^_W3k6GA3Liq$xj;25lLTkfL&I1yn@a6-ekS2Ei@jv>`miF zy%xtUanBpRWNaM@UX61pxhKh_4>kv<%Qev8Z1AT_3O#yzYrkF|ge&@sw*8u$^aSop z@#n$E>baVL+RDb{E+yVqYYkl63vB9~(TQTKJokzk7wNFc9pP zX5HA8IOx^c-Mr-L;)|wQKF`bDqq2&B zF-e-MqBcmvmX1!tj*d=c`mg|Qv&M^*4kbCAyg9H$?O`Y9{bc{klAIc;y~;nrhI_en zKKBmDJ@SSfcJKJXu2QrOCBY(oy zkw1}h`iBkr6QDowaIlMXINDzF=gQG=oq^p+IinP+tb5Kpn{f0@?~y3MRbDUIXLw22 z)FLEmh2b>U48uvKE%l|EpT8U(T%vK-?S1<@)por%*>%;r(omw`iEeG!z|Ew7fR){5 zR#eAIZU6a8pLJMi7Rt*7-fQrtp6?H|i^w-lO5VIQoZQ}jv%mW|nXu8CNNG*hO;jAJ zx4aU&|0MagSC=q#ca4{1joPGUDsFtf2Qn12;G5uf)jr5-mI;|v`@~|utpUrG4!b(+ zKKJx(mAjm5A8jQGn-;s8;+2gJB)7fl&o{UDB8L6snu*Z~`tu9!Q>3N};1h^ANliU$ zkow{osX`)b6OkM5-Cxq3G|I!smi zZhL4ilV&)5z2;9^keAcE-W+T{&+w5QZ=JVxc@e4Ahp&CIxs=AXQMQ{!dA);FN3Zqe zpKnWhhPV@6x`OFov8T7rxmniwEP4|idcN;P>)3b>{Uqr(^mFTC@`_d^F!l4Jm2P#8 z%GMezxBRDSfw~(U?|f!-14!}0UCQxaCE zdf6OmCK>67vr_$Oz4vB&vQ`zOYt_TsuUd5(;$b44yAodMEzixzf9|!nUTGypOz@&& zC%cdvD`BB&&NWRiB*t`sW8)4w`mtvZzIE_Q~`O5OM;tM3*=W@`G?v>wnbA3Zq5mhKkf*RX3d zzfh}gt84D#D^mo1$SqQJR}Fn`u!y2RRyFf11IoR#a%`U0+D@-mMnCsyrkmU9QC_hR zWpOE%LEA3gq9BQ3{$n={Q+K-`SQGARJCZ@hz{UQ}-L893_Wi{#80nDnhmOe=X>ore z3oc()ufg=;$_|%_ve5A9Wck{R>zvzX_PF|a^ z$K=0#pl@(@9}6FhOtssG7CZjqZZ{LV4RL9d9sWXJ6R--?6MvNb>ZGcEaiRPhHq>@Z z?7eAv<4v2Vw{D-_eAC=DJFnff`KC>~cJAIx+T70Vn`d7$@a-lZX66^zjackf=8p}1 z9}(Jlpj$Unz07Bgb3_lJygrZa!PhkTfM@7dy@hWgnKIh_zCKlt?%~(fx@`mA019EN zfjPM_7b{-YFg~NZIdJRu#U`F`%QW8~+~XDPxJ7qt|Ez^mEj3zeCBohoFFjZ<#m-^i z^!jxc(ea!8L_RFzynW;f6Bd@=!rY43~RR#YspJZn)pS z`~N@FbGFZ%g}A8DRWseE`**(Y>#x7lr%#_*Y47%#Ey?ONk4cy=u>7W1UcIqo`Cp~A zNwSvh*=!9fewKL=cM-XZvx0amdCyoOH%{)C3gkU+h1_~_n+oJz%l02y68bn5EMLX4 zhqXWBm~K zZ{)y?;x6XAR1{a2k;{uK>AjL1`Wn+a?z@$|kla%WxL+lQ`$tTk^d2OKF&o8I$(0JY zKDl)T-0R3q6mWNwdwv1;d*mhyxc@?KV*&R^A0>B94ySqdv*f0Xi^a3%l`oSk z8;4>LwsthQ|Na9xTraV4`yt!&<`>D8-itNim^{R^+EGRl_bhU#kJ%?~g50ush;}KS zpHFVt^+8VZ!hS%v^utf^=LX7=T&o&N@Db8Za{g%fx3~(qQ14WL%Rkb4Yall^9-1dL z|AE0ZCpi+mL^*F@Ua|)CRUFDlx_<8=H(_-#z3T6~$l*GIEXlLtQ2GG5E36hp9{Rzy znNu88*G=q4I4@tkMENkY77pi45PZn95) zE}6nue`SaKJZ=@}TG~Cv{d3rlP0TUAF+Xo-`+nwm!;2$YR8(1adV*SmI+k|nkaT{A}4VE-6{%G(mbra;m zaZ?*;^=GByb`9l8?m(k2N%o$IUi4S#N7buwt57cV;3GMbJI{9MSG{uCcQRrh?p;cf zyHdZb)IM={Q$KtX>&IK!E<0tHa`oc_k$xavlz!BHr0aXig&z1tawPZDY?pr3E0=v= zjM!HeWVz(#acUPRPU9Si@?r)cq1A{S<9LZIF1-U1Y$>Xjj_v9Q->!Gk8yQGBY;86RgQ$as)56SA)b+m&V znAmkB|ILuYe2+On@=!*41>4)qC#^2V$$z(#TW8#m|0EDXE&V3B%dHHZ(u=k*y_Fo^ zZ^Sso-+RbmZGf@M%DbQKp`XJT5U+k{9}cz*^#c`_#GR#FFfmU43-wMo3H~dq_W{a7 zYfPT>eyTvPRQykJaDQyv#tAB(b#2Hl$r1Nu%FA2l$j=XxL;S_`O70`%N;%x>pYdeq zKg6Jt?3AC!$fF&8R=fD~EIgGQm{Imguf`YtK|-!FjON`UJwvqZv#_h6?Oo3~^5CCe!ewvy`@b3wqNjHLPgCFB;ZE++5S9BuD<$=znh>+F-&dx-5V=4XtF z>D7Fy@z_aO8Y|@ZXnq#AgPdh9iPy2XZB~I8RKoj;F#V|9O7%Y4+`Ji$@leY4V^rMZ zJjH?f+p)Sy3WG~fh7a{zD-OsRd@(8R#f5QyMv&!-2XSHC$2i6Fs~ImPlL5OW$BHhA z`*m{btTx6eUfx7*!Z`F(@=!)P@3Z8c&ur zLE~cmkih>z?iQ{@d9>qOOu9L&bfB!^oseoGxWtL9a zXO!NjlRKTmN$&)?dvZ9%f#P|BT*-3yyKJ8^`^bOdi`vDD>yraBihC`&QUP}txyc+({e3&RDdRA0L4w31hQlpRe+SFb+~- z)~rSC=bVvLp4AB~%y-_RZ#U)?`eU+5)3JU)^` zb?H2GAvyRVChxo#lRS~!B{}lMT}rN$!>J$7BR7%5ZD4yi9u~ zpPZiatsSesia+^9F^C+Webgt;s*+0rrIITyoKHhe zr)Zwk_?|I&llD=&6$pr3t~a-;-&A~l&g5j zz%UY<-2v3G%eWFN{%vhNw>a9xhl z`)qR8izA?0nemYCitwim^V-Y17~a4OX{m>0x_`zj$P|A-6s zRbrgtPxqse>D*->$&m@;EZoTc%-eCSzv8ry-pJuJZnKovDd1Y<`Z=8Ro+P)J!)2fI zmW;c=KI$*ZNQys=hx#$*o86p?^6ROO)yp#Y2SB|NiLdW+%=T9n>lor>?1i=bV*#;j}qIEiPzs@+(3C~!(6U*93#Dq z?Rw4=ljS^}BuB~P_b*_woaVDz$z5tpY@R&L_OKskj8&3caq2hP&j_+yocjAN$}L%& z`V!#jec?WGdGo#2b)O(NWkOJtKFQR4^?7o8tRZ%NNZwb-l?&wkA9Av{V};WSvfXt;yy#}o*Yis+t zzde`j^0&@cu6|rgPJUFoa&h~}h5aoFvRrm5p7lF@AdsPU93zR-@AScp;`H|cdG~4c zL+e;vld*V#Zls&pA7rpCYabY-cHo~O4#F*+VEY}+$E+?k9^;O--#e1adro-=+e1G? zrjqQGy!Vqwd(400?kAV$XK^1Qm*;13A0`Js$Mk-j?O{KbU?kHj=DNTAC3#do(>`h^ zmgx6ue?xA<8p;t)aizb9fUKB(U#Fb!GA~h9R@Cgr^&&d*!^7GJITR!G44LL ze}Z|*xY&H~7i|AJbHsCu``>I|4TY8_?Gxjk!1i^_H|22S5Mt>C=;RY{u<>Wi^&tG^`CyHrG7eLfjq7M^6oQ|r}banJoyOi3jI7GWtL0- znkV{7jT??ejhp5dFeUp)jul;c3gv}*KcGg-#q0iYC3zsR`-iv}k^>Xt@IDafI&!#< z-~#DG8a_=tS-b(J?9PYhr59gP&#wsapK0>Z&UekOP&TE*jBu8>TAJL0gRT4kWif@z0 zVJxoBllvaI3+xyl$w3)O^48)H2rOYvi^&uBWO7f*aug^|{*ye&M#3?Y?0YulU1D{k z>|0N+WZWqGUPNwPmdmkE@(gz=Yu{eVo3PeV_Pvtaq;aF{J4S9}mZN>Tj^sbdbH>?M z*1lh-yiL|N%Dy*~n=)>ceZNm`Tb84J+3}S;!(GbScb4*YS?ehKK1Z%>+$j6LPHra4 z<=7{A&N%zZ+V`)NchK5K**AuOw{*xpqwIS&xoVc9ecADqJi}ee+IKDG&0Fgz`)(lD zF>aK7hsgD_9PP`FujD!7>`V47P>$jh?InCMtzv$j`EQWNVXPnG-a-z{DDDH~U{8!w zKR!wh^UEl|JV*{}zab97ElHmGD|xR;7PmwWaS`Lx-`^nj zgB-o$-bfCPjrm1--%AebqnKWCe?)GqfO~-4GYh!CBsWpOeU04498Udxgxr*IvHpr% z^Hg)3rELY=CFFJ$a4#UYCx=_`>XM!0%EsZEvur5IzG-re9C_kq$#rr#ja!Et{@tS3 z_)6Yu$Svi_6L&YcJ99Y1FVY!uD36-2{(u~q*tm^DfTfRreD zklT~xXrDOwPx2^cdHhjc*?>{@{a zon&8QENFa7ly}JLN7;83xq0J;^irPe+d;08M1eV3DadzQ;O|W#8@OK9J>d z?2|l-S!Un6DDQp)M%njKa%Z!8DOmP>iQI>?9PJaQ_>(+}S!Un&DenOTM%j1K&wB}< zvTW4#yN=vvvmEWq#-HSQ>4W*@MU8^ao1Cx-ZMy!a`XvF_qT)O z$E@yg_K`j?NP5m|k(;nObWt3;o9I2_adK0}K&Ch=x+MGVAXm29QSU!~o7{|XvGLG4 zOz#^H=5XUqdy>3^@|N8f*e>oqa)%1!eUx0afcqS|`2y~%qnt3F6?14;JSaY&qaV6kTPzO5T|o{^j9VYk zTQXKjdKLHA26|(0uejPt4oocmB<}`tW5&hg$uIgH$}@B19gOq?F|DM(U(o)2oxEZ| z{S>cw?ich!^6m)w0aZ;{(&WsF^(Ud6NG04x%6e56;LWQi}6`)BGCXVuARd@)JCxNyFY zaf+A6!*Q0NH`ZUx&-$GQd<<6ltmu;BS@(qrtBu98`ui;E-Dq4a4)pKfK93y6?Vx?K zdesm41@gclLGGk|VDBc%8MksQfkoOuPV!KPJ}XIoncU6H(H`@k^c^M#Cf45$+mAEP z8;{%BUSyv*^#}IF`f=9^<%yHrJbCYk$SVV8lK;d>E}CPUei!~Wi{!}xoUI*{3EE{O}{FUIM2X?rQR zWM|)RAIWjT>}w{X_p}-VURyo#zJ@oS~W0hp5xUj!5PQSakk8;u93HwNnnMcT$Z3FD}#@;~u8Ge+=|q5XeCpY20VYs!M&L zWLeCA;+{ZmT@I)9)icOx%(8x-V0#!Zr@RU7TfDe%9*=Q)ZoGo&Lc9O>-e5Q7kk*@Vway>cJ$2j?AKe;jEAWQNnCV4sAL%*C;W5A0G{SxD}zB)#^ z=AT!$!aUUc1sT}U}Y!CYj-za6}hX1~I%zrxX zAr`>kSwhbfZt}8Y{XOMZsULlf_4n^0_8l}D9PR8IFF4FHiXMFQOcA zsEv)U`ujBU;9~vIcsz?7m>73OL@)ZRq<9dgctCr|p-)KS^!K%h`51TJ(YAi4{xLg_ z*{8oJ*+Op8xRQOO&x$TxAL++Z0I471!hVFDP7$YZK|f;LO8fCL+E-^jVe;^iKGzBR z8fW1Ixw0L{;!o?{*N{78T*-uGo&tVJj>jix--FB%^N2g?Lm5fW6?$Hnw7LiFBMuCb;xwKA42a2l zp2w4is29&$vFk|kisJse5kH@$4rKDPxX{lbr~b$|Du_{$DQn(q86=>~NEPvfLrIH<;gJOw7-U7scP103 zJ?5$(Q7pb9Ok& ze}7K?;T%r>3;O~8DM`QdhR*>dgLGem4M>`=^c+yKI>?Y5E4rlXQqKY7RtulWZ9 zSI+?x#>D!I^O5u%Flpu3{X?9d12*Px(ks7|j6)y9AA}*6biIi~9h*>0`~COs$o^ls z5(}1Lj3F~j;=WMwwP0f0H`)Gu=E!1xImGtRzOu1O^0&A!PD4(1YM(~)E^M2$kJ=@7 zoQ21+FlEQF@pvlRFJ->VxL7~LsUPAb_n@5zTP~*@aaQG?SCJ#Bzv9CFPC3GVtzuc+ z+gJe|Q*1*fF8iLnWNrAU-HI-49QS!>-#K69zGa`d(7uq9Tyf$3BgUPlj-vat_NBDn zG-2nRvXAspOzP)r*q{5YAvSK}cauA76_AOKOW1U^bQ9Y{zhDihB)^CY{StCIMO^5Y z7`IZtXkSYEO|bu*eWXuz&abc^;)?nq?kC+3{k`+hc&L+>YdjVs{VfNa{G<0XcaR@5 z2KN~be|m=gKiAijLjzdJ5%@;72bh{%uKUt^355NCJSE9p&kFrNk2s9YSK{>doM1+A zAEJI-8!=A((C-THP9w&BEYgps7^{@+hyGm+w8!MBA77+gFrzs6C9fZnC%@$NL)^pE zi?N95{g+68`6>=wO5;JC{DZa_C%qT`0tkCgXP=l}abx5z$>E;H_Asu%Drr2#h4#fb z>3wd2eUlNrvHpq+^~N~q-C3Yl++K2dewkjOed2!7_8pDb7mkPKHF4qm9C8}p^BnM^ z`)ZGR^?NAAiE_ju(y54jr+t(AmR@n1f6*A@G;VLD+_G__;{IN8GX>mPatCubjqfMP z-C`W#Pxf2UCE52ma*I|w%D%rQcUuAXC2~sz+&OZ07I5DucPfX|_+I>r23WewKCA7M z?Qe~@)6IQp$KIluB zUdZ+x%nw;(OrGLX&u{ZNoZ?x20e9LyNRT^epE3KWA4U5#GqkJddV3W)=`|I}626$^ zA93mrnwQ8R6Q}!;;=XKcqvHNQQGdg@QE`8YT&IA0Be{M7r?}6%-sC^UGp@H-JijgC zKiH`B7#748#k07d_IOsjD6SCCOZ3H$6VLCbpNr!8&kDvvaVjp1=WyJ_X@34I%0)bn ziqo%Bid0KbgQow25c_@dI{}j(v<6`mrNP+(zW9K1>D~e}vKkf0XcnRZK z@$%!u^Qv{;kK;aD_Kg@rdJ;M5MIH8nl~fcL#&e95-b*PL@r-*W{vU=gY2E&8a=3oM zNuOBF_v^{M-5O%^z1Bn5kXy>(^t`&0+*#ue*(YnC?$dk8;rE0wz1P~gNH>$q`@3Ut zZE{m456^Jf{*F6oNpdH-yuT9`_gm!3CTPtFd2b{)lf!8qdKC#I-BQ5aNA6Go zca~hWfcqG^`2z0KA6VgazQ|ZZrg>LfIPZp>iFZj{IPXR|^8ZoS#d@Fec=`u(F8Zi`(){$j%cbOw z6>xg*(lrkE!E}Akg630=2j)M`r$5eo{{q@ow0_whiGwB6t)za73+MYKL6(ctKFCVf zMKXGAP#W>BUikGs!x+)sNP zXgtC=(0Kef^U&?|^Y1dZVH-*qL!^7yKJE{feT#d4WZYnvlHy8oJ{;(c#S8A=NS`1F zCN^(;Dx!DHo$0@%SN;8RpcnS3U8iLAf{E$<+M}#jetv{}9juc4Exn#vkEiNnpJrIUAqdavDK>%+V`qeZpU&J_IX}p zJ}WQYxG9;PuXL@ndlL@VU!C;k+uc4YtZX$`ZAj`ZcWkBd;{IBtksN8XE2uh9o4qPo zOim`Z`h$(h2`jv0!8LAeFSM$?tCD8DRc|gdlV)Yn<>kehZl%>b((X2sW42vdUff&h zUv*V7+iom0Ta(P!GvAPGX*Alim43UMOwU)U?Gsz;{k@e=(sW-pwY$~pOi@2+4!CBy zQmxioa|zLMzdKVo+^8kT+x2SFoVF%AX!`RGx7&@RdBcfTZ*Q&H?w(AVTNjQTsdaDc z)v9J&xlw7=l2(H9b?sKK->sNCcDIi2t@L`+vlSE6sJCjB?qpJF%`G%g@D=M-vEEMI zTItnxG%9mFE6<$l)K~>0TC?3+zve2N18jfoh_lbx-PDntwzt-s_j-Fyd$--M^y}?b zQtofwT&{Hc_1Q*k`ed(PGdFZAO_SYCy0uzzj3*yHuyY`a(QpGrtND$V-rj&6O{9h-79F+GH3+n~VoRV&R7hOO7HA34&h^?Hbzy=|P9 z8V&x2BS(6*z6D6DUzycWr`vv2&8hH1)}bpbV5{3I{fhT~t6lHaoMWx07I(F7z0%m- zs@7*~z3F~;VYYA4?v9eyLX!>F(JDSyZ#4h!thLRj-IExw&6~FyWtBFH$7^nA)a=#y zh+W>AG#LbgCUl1~T(>LTxq2&U+Gu-GrXMlAquXx!3V-UZg+>G2OXgLW>nvQ?Zg$Me z2>F<8d-gDnV#dyxM{s>0&eU#rSe^6(CK+mhz0REGuy3tP-q-E|2u_y@v&lPaSFJub z-``QMHL7Ye^+9biKOk84*F(2`!WaBZ;>!W--IgQC89k&&+EdG1T&dP<8b0>cPj}{P z-C7ED-Nj{Wrk-(8>GT#F1A4yFIO5H-Gp@@t`ct;H(*R6>Z(r=!T75V*Y}vW6d9!S| zv4v}Qcgx)0sx)pmjEkh_hsa<0NmD`)OXYUs`q`8;_Z>b^>zc0S z-g?WfjM}2jxm&hwwK>d8sC92Rf+^8X@)CMB`_B0o-CsH3H8ffLihzQbFpucF2N#5&ro(&n^Q z-?yX|c?13T0e=UuJ5PPC)igE|DTAw8JJTcVihk z@ZMBsbrG3?10MvHHbmWu9nX0+7~JihUcF&M%jv-GhyDuFq}4RNwf(gw?v?EHtnMa|Qdh1q9TXtAkw8P5c ztx2cf?RnVTiy~Rd%p}D`^wi}p_l!fM= z+VNV$Ts33&zQ(?G731p4M11D#ln>$ir0J@X>Gnc*)=hBU+jjQ8!v;bMr>34Qb_NHw z60%z`JZWp2R^N=O`pCy<+&ua6E7MD;nb!D=!ny@y{W1hKL&%0@2x^FIJpeIf+;6MN z9$OAIyhC;ErPuJ@%3RCtywzH=^}t3qT21uaT|pSnq&ali4LzwF1uWpg6i_WbtIVt)cPTM7B!+^<>bGluj?1I&{tMwx% z{R*_axCIl0y0oor7ZVm}JG<=#ERV0VWtlBGwRc3x^}mgxYBgp7S`@-%iLVI zHfJ8(z0DT0wXQ$QF8zUQU-m0a-@LUpUpZcv?q)_c^zEBh+Qv017yCM_+uE($v*od$_<88>2Dn_D>fO!GLZeqpdW~AG zGqB)@O{cd8!F8f?G+m;4Kiw46*n-oqU#sq-wjSC2y@%B*oHkTf@9n7c`g_~Qv8Xl& z9aV@8{EI?NW>J4jh)|{~CyvYRL>)rPT_kEScSPkfqiszje-=1Uf8-IIYqxajO@56%y3(Pb`9+{(M>pBKG; z3j-cIbM=@ySkgDQbnpyT-O;xDlU=(0Xr|pgw!oEqdVZ^A>o|KR#segap~A9%8nU}6 z3t{85yZFl8nyn0ia)=zL_ZBJ*clQm77z%$&_E*Q&Zmn`u#`=pWtg@-k{L!&q2hlxn z0;a8PCv8f@nvcG8j;V9Kx2;=0UQ6eQUQ)BgE*7!bdR+AB(_g^%YW5K5hG?eUu$cxA zy~~t^6)}rm+%|KZStiV8oO0W);Mw_lqv}e1drqsNvhJR4{h?-!q}S=X2U_Rw>F{7M zari#rk*#4jPcu>7461r3Ow3FDy~>qe7L;9)Q%w4t>?qe_cjhV_>E?ZV@}IL#*hBAh z`j9=SlTrN>wnyMj-enJC$>4BL`$TY*)j8lyr%8Ruv@?59eA%E_wnu6pGf?HV=*TJ2 z0l0982E(ze7Ndvx?7Bv~Z;S53HUn*4XdLyknLSTb{N9MI^2+nJ9n-tgt<45UKC;zj z&tDaPOPQ|qQ`VO~>B|ES*Z%QJV__gUtnufBHG?y`6qiBip+6@*9Goyy>)UhYme#E8 z)upy&D*efs%B+YzwbopJJ|iNn3`L}sfe0;@Wq7)JzS5>gtlWc&^t8+n`Ki#x+%4+; zuwj+zk9T$!ROJQ+L7Z9})_8qk&2oisIFMrr_sUf8ZOm>QGyHjHicg z{m8-`_PG4YgcJUbZq4o~?pZpW2*SEr!?qu3NIIu9r^D*>yrj9a(LP+Utpl4Go72OK zn`XFnY2H+CRny6_i9UpDIqT;Un`-URf{Q!sV7mRx!H^FsIO2nfbikVjI=JW+l{)e# z=qRLbayv@H=Y(}SGprk&pE}BK@}#ydulI76*GFWPEA_#Zou0wkj2za+q+s`Yxj}AU z$Eve(NQZ*lo@AwWG!PP0NkC8)p3DFWW&uALr~L_9Bx?CNp+qg9LUXt#3i=aJgOjJz z)xh8?PQ~OjdZTh02ci|G;l-Vb&S~_ba~cPthc3DFPT<`bZDa$0^7mkS_G?uuwx!4iKr#L)cF!I==If;C*~7RI zbFamY>><)tR3_O<)3Y^uW7cGbG3~Z(wP_Dl_B3|mrsrBy-<}(q_EyfH;2-bZxo*?I z?@{|USK)UZaGu>ZXMF=6TCtbNeFDC;tGOKq?m?t=c9$I7bi7Aw1Fto=ymIJfC31Jq z-P5p;cM5&I4-DU9Jb{{dE^{^3YtBmU0WB>{B%hgd$S1t!)^7V~tp&;SOz>o6cmD9m zsR?V`!Z>OA%(rSs$o!t}4%u=yJV@(pdkOnfwrP&XN(;nvao8s(@W|o?+kVaK@C5F)_%eNr z$i)QY_G{c2O&_!AuDj4OFHgHSybHEfWcwo7nl$veA4|`m7yc&Y?_NCOg`iuS!q{mX zM0GsO6W14q&TcqtFPwuP6OzX`BNF?_HMG-#ovgQizu!zW@FU!Az8oN%iQGios3^IdPONVfye1<~9vpAatn8$+R~Is>B|4TJER&U#fCqAogni2+Mo9g3rAJ za*w>+VfT(7>?#G@Kz@74e``tUkG$81hmrnHE3q$a+eK~+xmAVvus^TOBVVwsBVT}X z`p4Ah3)bihzR~R|`6vjsmyWqIh=vOW+nt0n5_TE)oLSq1v&i%w2`XIY@sho4FA1Ai zgao57T<3;ixGLFEU#$80%e4*;P2#lM`}TLL-FREFKn@RnMt?ahj zit1$2_CJE@+d3?nwpM$&VDB~TO}+j80K16xOD9xsUmUJ(AAXg;`?zzs(VCuxHCZ