浏览代码
Moved shadow related files into ShaderLibrary and common to reflect their general usage.
Moved shadow related files into ShaderLibrary and common to reflect their general usage.
Added support for the new shadow library to fptl. Introduced a new shadow include inline file to support different shadow setups for different light loops per project. Restructured the code a bit in order to support multiple instances per project. Fixed and issue with broken shaders when one of the samplers was set to 0./main
uygar
8 年前
当前提交
1d081a77
共有 71 个文件被更改,包括 1368 次插入 和 785 次删除
-
4Assets/ScriptableRenderPipeline/AdditionalLightData.cs
-
2Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
-
1Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightLoop.cs
-
4Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Lighting.hlsl
-
13Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
-
7Assets/ScriptableRenderPipeline/RenderPasses/ShadowRenderPass.cs
-
213Assets/ScriptableRenderPipeline/fptl/FptlLighting.cs
-
56Assets/ScriptableRenderPipeline/fptl/LightingTemplate.hlsl
-
2ProjectSettings/ProjectVersion.txt
-
5Assets/ScriptableRenderPipeline/common/Shadow/ShadowBase.cs.hlsl
-
14Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Shadow.hlsl
-
43Assets/ScriptableRenderPipeline/common/Shadow/ShadowBase.cs
-
2Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Resources/ShadowBlurMoments.compute
-
13Assets/ScriptableRenderPipeline/common/Shadow/Shadow.cs
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/ShadowContext.hlsl.meta
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/ShadowDispatch.hlsl.meta
-
94Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs.hlsl.orig
-
8Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs.hlsl.orig.meta
-
9Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow.meta
-
25Assets/ScriptableRenderPipeline/ShadowIncludes.inl
-
8Assets/ScriptableRenderPipeline/ShadowIncludes.inl.meta
-
9Assets/ScriptableRenderPipeline/common/Shadow.meta
-
26Assets/ScriptableRenderPipeline/fptl/ShadowContext.hlsl
-
9Assets/ScriptableRenderPipeline/fptl/ShadowContext.hlsl.meta
-
36Assets/ScriptableRenderPipeline/fptl/ShadowDispatch.hlsl
-
9Assets/ScriptableRenderPipeline/fptl/ShadowDispatch.hlsl.meta
-
9Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Resources.meta
-
9Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Shadow.hlsl.meta
-
277Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
-
9Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl.meta
-
9Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithmsCustom.hlsl.meta
-
9Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowMoments.hlsl.meta
-
9Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowSampling.hlsl.meta
-
133Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowTexFetch.hlsl
-
9Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowTexFetch.hlsl.meta
-
12Assets/ScriptableRenderPipeline/common/Shadow/Shadow.cs.meta
-
9Assets/ScriptableRenderPipeline/common/Shadow/ShadowBase.cs.hlsl.meta
-
12Assets/ScriptableRenderPipeline/common/Shadow/ShadowBase.cs.meta
-
260Assets/ScriptableRenderPipeline/common/Shadow/ShadowUtilities.cs
-
12Assets/ScriptableRenderPipeline/common/Shadow/ShadowUtilities.cs.meta
-
12Assets/ScriptableRenderPipeline/common/Shadow/VectorArray.cs.meta
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.hlsl.meta
-
12Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.cs.meta
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowAlgorithms.hlsl.meta
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowAlgorithmsCustom.hlsl.meta
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs.hlsl.meta
-
12Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs.meta
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowContext.hlsl.meta
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowDispatch.hlsl.meta
-
114Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowTexFetch.hlsl
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowTexFetch.hlsl.meta
-
222Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowUtilities.cs
-
12Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowUtilities.cs.meta
-
12Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/VectorArray.cs.meta
-
259Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowAlgorithms.hlsl
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowSampling.hlsl.meta
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowMoments.hlsl.meta
-
9Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Resources.meta
-
0/Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithmsCustom.hlsl
-
0/Assets/ScriptableRenderPipeline/common/Shadow/ShadowBase.cs.hlsl
-
0/Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/ShadowDispatch.hlsl
-
0/Assets/ScriptableRenderPipeline/common/Shadow/VectorArray.cs
-
0/Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/ShadowContext.hlsl
-
0/Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowSampling.hlsl
-
0/Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Shadow.hlsl
-
0/Assets/ScriptableRenderPipeline/common/Shadow/ShadowBase.cs
-
0/Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowMoments.hlsl
-
0/Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Resources
-
0/Assets/ScriptableRenderPipeline/common/Shadow/Shadow.cs
|
|||
m_EditorVersion: 2017.1.0a5 |
|||
m_EditorVersion: 2017.1.0a6 |
|
|||
fileFormatVersion: 2 |
|||
guid: b0e81431fe3a7604fb9f9dd2a96bd7e0 |
|||
timeCreated: 1491321445 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: e7e55b7306a2b2f43886918882a8935a |
|||
timeCreated: 1491321445 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// |
|||
// This file was automatically generated from Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs. Please don't edit by hand. |
|||
// |
|||
|
|||
#ifndef SHADOWBASE_CS_HLSL |
|||
#define SHADOWBASE_CS_HLSL |
|||
// |
|||
// UnityEngine.Experimental.Rendering.HDPipeline.GPUShadowType: static fields |
|||
// |
|||
#define GPUSHADOWTYPE_POINT (0) |
|||
#define GPUSHADOWTYPE_SPOT (1) |
|||
#define GPUSHADOWTYPE_DIRECTIONAL (2) |
|||
#define GPUSHADOWTYPE_MAX (3) |
|||
#define GPUSHADOWTYPE_UNKNOWN (3) |
|||
#define GPUSHADOWTYPE_ALL (3) |
|||
|
|||
// |
|||
<<<<<<< HEAD |
|||
// UnityEngine.Experimental.Rendering.HDPipeline.GPUShadowAlgorithm: static fields |
|||
// |
|||
#define GPUSHADOWALGORITHM_PCF_1TAP (0) |
|||
#define GPUSHADOWALGORITHM_PCF_9TAP (1) |
|||
#define GPUSHADOWALGORITHM_VSM (8) |
|||
#define GPUSHADOWALGORITHM_EVSM_2 (16) |
|||
#define GPUSHADOWALGORITHM_EVSM_4 (17) |
|||
#define GPUSHADOWALGORITHM_MSM_HAM (24) |
|||
#define GPUSHADOWALGORITHM_MSM_HAUS (25) |
|||
#define GPUSHADOWALGORITHM_CUSTOM (256) |
|||
======= |
|||
// UnityEngine.Experimental.Rendering.HDPipeline.GPUShadowSampling: static fields |
|||
// |
|||
#define GPUSHADOWSAMPLING_PCF_1TAP (0) |
|||
#define GPUSHADOWSAMPLING_PCF_9TAPS_ADAPTIVE (1) |
|||
#define GPUSHADOWSAMPLING_VSM_1TAP (2) |
|||
#define GPUSHADOWSAMPLING_MSM_1TAP (3) |
|||
>>>>>>> master |
|||
|
|||
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.ShadowExp.ShadowData |
|||
// PackingRules = Exact |
|||
struct ShadowData |
|||
{ |
|||
float4x4 worldToShadow; |
|||
float4 scaleOffset; |
|||
float2 texelSizeRcp; |
|||
uint id; |
|||
uint shadowType; |
|||
uint payloadOffset; |
|||
int lightType; |
|||
float bias; |
|||
float normalBias; |
|||
}; |
|||
|
|||
// |
|||
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.ShadowExp.ShadowData |
|||
// |
|||
float4x4 GetWorldToShadow(ShadowData value) |
|||
{ |
|||
return value.worldToShadow; |
|||
} |
|||
float4 GetScaleOffset(ShadowData value) |
|||
{ |
|||
return value.scaleOffset; |
|||
} |
|||
float2 GetTexelSizeRcp(ShadowData value) |
|||
{ |
|||
return value.texelSizeRcp; |
|||
} |
|||
uint GetId(ShadowData value) |
|||
{ |
|||
return value.id; |
|||
} |
|||
uint GetShadowType(ShadowData value) |
|||
{ |
|||
return value.shadowType; |
|||
} |
|||
uint GetPayloadOffset(ShadowData value) |
|||
{ |
|||
return value.payloadOffset; |
|||
} |
|||
int GetLightType(ShadowData value) |
|||
{ |
|||
return value.lightType; |
|||
} |
|||
float GetBias(ShadowData value) |
|||
{ |
|||
return value.bias; |
|||
} |
|||
float GetNormalBias(ShadowData value) |
|||
{ |
|||
return value.normalBias; |
|||
} |
|||
|
|||
|
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: 84fb1d4060005f846a843b1c1bf1d48d |
|||
timeCreated: 1490622303 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d52d6e1ad3dca474ebd73d054d17fb2e |
|||
folderAsset: yes |
|||
timeCreated: 1491314187 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// This file is inlined by ShaderLibrary/Shadow/Shadow.hlsl twice. |
|||
// Each time either SHADOW_CONTEXT_INCLUDE or SHADOW_DISPATCH_INCLUDE is defined. |
|||
// In the case of SHADOW_CONTEXT_INCLUDE a valid path must be given to a file that contains |
|||
// the code to initialize a shadow context. |
|||
// SHADOW_DISPATCH_INCLUDE is optional. |
|||
|
|||
#ifdef SHADOW_CONTEXT_INCLUDE |
|||
# ifdef SHADOW_TILEPASS |
|||
# include "HDRenderPipeline/Lighting/TilePass/ShadowContext.hlsl" |
|||
# elif defined( SHADOW_FPTL ) |
|||
# include "fptl/ShadowContext.hlsl" |
|||
# else |
|||
# error "No valid path to the shadow context has been given." |
|||
# endif |
|||
#endif |
|||
|
|||
#ifdef SHADOW_DISPATCH_INCLUDE |
|||
# ifdef SHADOW_TILEPASS |
|||
# include "HDRenderPipeline/Lighting/TilePass/ShadowDispatch.hlsl" |
|||
# elif defined( SHADOW_FPTL ) |
|||
# include "fptl/ShadowDispatch.hlsl" |
|||
# else |
|||
// It's ok not to have a dispatcher include as it only acts as an override |
|||
# endif |
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: cbc2765f95de56a47a8f39f5f1badd58 |
|||
timeCreated: 1491314187 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d49f97c73daab8a4a8d389c977c2345f |
|||
folderAsset: yes |
|||
timeCreated: 1491321440 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
|
|||
// This can be custom for each project and needs to be in sync with the ShadowMgr |
|||
|
|||
#define SHADOWCONTEXT_MAX_TEX2DARRAY 1 |
|||
#define SHADOWCONTEXT_MAX_TEXCUBEARRAY 0 |
|||
#define SHADOWCONTEXT_MAX_SAMPLER 0 |
|||
#define SHADOWCONTEXT_MAX_COMPSAMPLER 1 |
|||
|
|||
SHADOWCONTEXT_DECLARE( SHADOWCONTEXT_MAX_TEX2DARRAY, SHADOWCONTEXT_MAX_TEXCUBEARRAY, SHADOWCONTEXT_MAX_COMPSAMPLER, SHADOWCONTEXT_MAX_SAMPLER ); |
|||
|
|||
TEXTURE2D_ARRAY(_ShadowmapExp_PCF); |
|||
SAMPLER2D_SHADOW(sampler_ShadowmapExp_PCF); |
|||
|
|||
StructuredBuffer<ShadowData> _ShadowDatasExp; |
|||
StructuredBuffer<int4> _ShadowPayloads; |
|||
|
|||
ShadowContext InitShadowContext() |
|||
{ |
|||
ShadowContext sc; |
|||
sc.shadowDatas = _ShadowDatasExp; |
|||
sc.payloads = _ShadowPayloads; |
|||
sc.tex2DArray[0] = _ShadowmapExp_PCF; |
|||
sc.compSamplers[0] = sampler_ShadowmapExp_PCF; |
|||
return sc; |
|||
} |
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: 30016f0dcc663b14483b62ccf2e8a7ce |
|||
timeCreated: 1491395507 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#define SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL // enables hardcoded resources and algorithm for directional lights |
|||
#define SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL // enables hardcoded resources and algorithm for punctual lights |
|||
|
|||
// example of overriding directional lights |
|||
#ifdef SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL |
|||
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L ) |
|||
{ |
|||
Texture2DArray tex = shadowContext.tex2DArray[0]; |
|||
SamplerComparisonState compSamp = shadowContext.compSamplers[0]; |
|||
uint algo = GPUSHADOWALGORITHM_PCF_9TAP; |
|||
|
|||
return EvalShadow_CascadedDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L ); |
|||
} |
|||
|
|||
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS ) |
|||
{ |
|||
return GetDirectionalShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L ); |
|||
} |
|||
#endif |
|||
|
|||
|
|||
// example of overriding punctual lights |
|||
#ifdef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL |
|||
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L ) |
|||
{ |
|||
// example for choosing the same algo |
|||
Texture2DArray tex = shadowContext.tex2DArray[0]; |
|||
SamplerComparisonState compSamp = shadowContext.compSamplers[0]; |
|||
uint algo = GPUSHADOWALGORITHM_PCF_9TAP; |
|||
return EvalShadow_PunctualDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L ); |
|||
} |
|||
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS ) |
|||
{ |
|||
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L ); |
|||
} |
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: 631ee816f7a634d48ae2c70c43a46e98 |
|||
timeCreated: 1491395507 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: f2f1273335a3dc54686dd5620bfc6790 |
|||
folderAsset: yes |
|||
timeCreated: 1491321440 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 3d03971a8848ee14bb29a3c4ee9790b8 |
|||
timeCreated: 1491321444 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// Various shadow algorithms |
|||
// There are two variants provided, one takes the texture and sampler explicitly so they can be statically passed in. |
|||
// The variant without resource parameters dynamically accesses the texture when sampling. |
|||
|
|||
// Helper function to offset depth based on the surface normal and light direction. |
|||
// If the light hits the surface perpendicularly there will be no offset. |
|||
float3 EvalShadow_NormalBias( float3 normalWS, float NoL, float2 texelSize, float normalBias ) |
|||
{ |
|||
return max( texelSize.x, texelSize.y ) * normalBias * (1.0 - NoL) * normalWS; |
|||
} |
|||
|
|||
// function called by spot, point and directional eval routines to calculate shadow coordinates |
|||
float3 EvalShadow_GetTexcoords( ShadowData sd, float3 positionWS ) |
|||
{ |
|||
float4 posCS = mul( float4( positionWS, 1.0 ), sd.worldToShadow ); |
|||
posCS.z -= sd.bias * posCS.w; |
|||
float3 posNDC = posCS.xyz / posCS.w; |
|||
// calc TCs |
|||
float3 posTC = posNDC * 0.5 + 0.5; |
|||
posTC.xy = posTC.xy * sd.scaleOffset.xy + sd.scaleOffset.zw; |
|||
#if UNITY_REVERSED_Z |
|||
posTC.z = 1.0 - posTC.z; |
|||
#endif |
|||
return posTC; |
|||
} |
|||
|
|||
int EvalShadow_GetCubeFaceID( float3 dir ) |
|||
{ |
|||
// TODO: Use faceID intrinsic on console |
|||
float3 adir = abs(dir); |
|||
|
|||
// +Z -Z |
|||
int faceIndex = dir.z > 0.0 ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z; |
|||
|
|||
// +X -X |
|||
if (adir.x > adir.y && adir.x > adir.z) |
|||
{ |
|||
faceIndex = dir.x > 0.0 ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X; |
|||
} |
|||
// +Y -Y |
|||
else if (adir.y > adir.x && adir.y > adir.z) |
|||
{ |
|||
faceIndex = dir.y > 0.0 ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y; |
|||
} |
|||
return faceIndex; |
|||
} |
|||
|
|||
|
|||
// |
|||
// Point shadows |
|||
// |
|||
float EvalShadow_PointDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L ) |
|||
{ |
|||
// load the right shadow data for the current face |
|||
int faceIndex = EvalShadow_GetCubeFaceID( L ) + 1; |
|||
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; |
|||
uint payloadOffset = GetPayloadOffset( sd ); |
|||
// normal based bias |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); |
|||
// get shadowmap texcoords |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); |
|||
// get the algorithm |
|||
uint shadowType, shadowAlgorithm; |
|||
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|||
// sample the texture according to the given algorithm |
|||
uint texIdx, sampIdx; |
|||
float slice; |
|||
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx ); |
|||
} |
|||
|
|||
#define EvalShadow_PointDepth_( _samplerType ) \ |
|||
float EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \ |
|||
{ \ |
|||
/* load the right shadow data for the current face */ \ |
|||
int faceIndex = EvalShadow_GetCubeFaceID( L ) + 1; \ |
|||
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; \ |
|||
uint payloadOffset = GetPayloadOffset( sd ); \ |
|||
/* normal based bias */ \ |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \ |
|||
/* get shadowmap texcoords */ \ |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|||
/* sample the texture */ \ |
|||
float slice; \ |
|||
UnpackShadowmapId( sd.id, slice ); \ |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|||
} |
|||
EvalShadow_PointDepth_( SamplerComparisonState ) |
|||
EvalShadow_PointDepth_( SamplerState ) |
|||
#undef EvalShadow_PointDepth_ |
|||
|
|||
// |
|||
// Spot shadows |
|||
// |
|||
float EvalShadow_SpotDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L ) |
|||
{ |
|||
// load the right shadow data for the current face |
|||
ShadowData sd = shadowContext.shadowDatas[index]; |
|||
uint payloadOffset = GetPayloadOffset( sd ); |
|||
// normal based bias |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); |
|||
// get shadowmap texcoords |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); |
|||
// get the algorithm |
|||
uint shadowType, shadowAlgorithm; |
|||
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|||
// sample the texture according to the given algorithm |
|||
uint texIdx, sampIdx; |
|||
float slice; |
|||
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx ); |
|||
} |
|||
|
|||
#define EvalShadow_SpotDepth_( _samplerType ) \ |
|||
float EvalShadow_SpotDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \ |
|||
{ \ |
|||
/* load the right shadow data for the current face */ \ |
|||
ShadowData sd = shadowContext.shadowDatas[index]; \ |
|||
uint payloadOffset = GetPayloadOffset( sd ); \ |
|||
/* normal based bias */ \ |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \ |
|||
/* get shadowmap texcoords */ \ |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|||
/* sample the texture */ \ |
|||
float slice; \ |
|||
UnpackShadowmapId( sd.id, slice ); \ |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|||
} |
|||
EvalShadow_SpotDepth_( SamplerComparisonState ) |
|||
EvalShadow_SpotDepth_( SamplerState ) |
|||
#undef EvalShadow_SpotDepth_ |
|||
|
|||
// |
|||
// Punctual shadows for Point and Spot |
|||
// |
|||
float EvalShadow_PunctualDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L ) |
|||
{ |
|||
// load the right shadow data for the current face |
|||
int faceIndex = 0; |
|||
// get the algorithm |
|||
uint shadowType, shadowAlgorithm; |
|||
UnpackShadowType( shadowContext.shadowDatas[index].shadowType, shadowType ); |
|||
|
|||
[branch] |
|||
if( shadowType == GPUSHADOWTYPE_POINT ) |
|||
{ |
|||
faceIndex = EvalShadow_GetCubeFaceID( L ) + 1; |
|||
} |
|||
|
|||
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; |
|||
uint payloadOffset = GetPayloadOffset( sd ); |
|||
// normal based bias |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); |
|||
// get shadowmap texcoords |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); |
|||
// sample the texture according to the given algorithm |
|||
uint texIdx, sampIdx; |
|||
float slice; |
|||
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|||
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx ); |
|||
} |
|||
|
|||
#define EvalShadow_PunctualDepth_( _samplerType ) \ |
|||
float EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \ |
|||
{ \ |
|||
/* load the right shadow data for the current face */ \ |
|||
int faceIndex = 0; \ |
|||
/* get the shadow type */ \ |
|||
uint shadowType; \ |
|||
UnpackShadowType( shadowContext.shadowDatas[index].shadowType, shadowType ); \ |
|||
\ |
|||
[branch] \ |
|||
if( shadowType == GPUSHADOWTYPE_POINT ) \ |
|||
{ \ |
|||
faceIndex = EvalShadow_GetCubeFaceID( L ) + 1; \ |
|||
} \ |
|||
\ |
|||
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; \ |
|||
uint payloadOffset = GetPayloadOffset( sd ); \ |
|||
/* normal based bias */ \ |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \ |
|||
/* get shadowmap texcoords */ \ |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|||
/* sample the texture */ \ |
|||
float slice; \ |
|||
UnpackShadowmapId( sd.id, slice ); \ |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|||
} |
|||
EvalShadow_PunctualDepth_( SamplerComparisonState ) |
|||
EvalShadow_PunctualDepth_( SamplerState ) |
|||
#undef EvalShadow_PunctualDepth_ |
|||
|
|||
// |
|||
// Directional shadows (cascaded shadow map) |
|||
// |
|||
int EvalShadow_GetSplitSphereIndexForDirshadows( float3 positionWS, float4 dirShadowSplitSpheres[4] ) |
|||
{ |
|||
float3 fromCenter0 = positionWS.xyz - dirShadowSplitSpheres[0].xyz; |
|||
float3 fromCenter1 = positionWS.xyz - dirShadowSplitSpheres[1].xyz; |
|||
float3 fromCenter2 = positionWS.xyz - dirShadowSplitSpheres[2].xyz; |
|||
float3 fromCenter3 = positionWS.xyz - dirShadowSplitSpheres[3].xyz; |
|||
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3)); |
|||
|
|||
float4 dirShadowSplitSphereSqRadii; |
|||
dirShadowSplitSphereSqRadii.x = dirShadowSplitSpheres[0].w; |
|||
dirShadowSplitSphereSqRadii.y = dirShadowSplitSpheres[1].w; |
|||
dirShadowSplitSphereSqRadii.z = dirShadowSplitSpheres[2].w; |
|||
dirShadowSplitSphereSqRadii.w = dirShadowSplitSpheres[3].w; |
|||
|
|||
if( distances2.w > dirShadowSplitSphereSqRadii.w ) |
|||
return -1; |
|||
|
|||
float4 weights = float4( distances2 < dirShadowSplitSphereSqRadii ); |
|||
weights.yzw = saturate( weights.yzw - weights.xyz ); |
|||
|
|||
return int( 4.0 - dot( weights, float4(4.0, 3.0, 2.0, 1.0 ) ) ); |
|||
} |
|||
|
|||
uint EvalShadow_LoadSplitSpheres( ShadowContext shadowContext, int index, out float4 splitSpheres[4] ) |
|||
{ |
|||
uint offset = GetPayloadOffset( shadowContext.shadowDatas[index] ); |
|||
|
|||
splitSpheres[0] = asfloat( shadowContext.payloads[offset + 0] ); |
|||
splitSpheres[1] = asfloat( shadowContext.payloads[offset + 1] ); |
|||
splitSpheres[2] = asfloat( shadowContext.payloads[offset + 2] ); |
|||
splitSpheres[3] = asfloat( shadowContext.payloads[offset + 3] ); |
|||
return offset + 4; |
|||
} |
|||
|
|||
float EvalShadow_CascadedDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L ) |
|||
{ |
|||
// load the right shadow data for the current face |
|||
float4 dirShadowSplitSpheres[4]; |
|||
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); |
|||
int shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres ); |
|||
if( shadowSplitIndex < 0 ) |
|||
return 1.0; |
|||
|
|||
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; |
|||
// normal based bias |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); |
|||
// get shadowmap texcoords |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); |
|||
|
|||
// sample the texture |
|||
uint texIdx, sampIdx; |
|||
float slice; |
|||
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|||
|
|||
uint shadowType, shadowAlgorithm; |
|||
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|||
|
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx ); |
|||
} |
|||
|
|||
#define EvalShadow_CascadedDepth_( _samplerType ) \ |
|||
float EvalShadow_CascadedDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \ |
|||
{ \ |
|||
/* load the right shadow data for the current face */ \ |
|||
float4 dirShadowSplitSpheres[4]; \ |
|||
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); \ |
|||
uint shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres ); \ |
|||
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \ |
|||
/* normal based bias */ \ |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \ |
|||
/* get shadowmap texcoords */ \ |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|||
/* sample the texture */ \ |
|||
float slice; \ |
|||
UnpackShadowmapId( sd.id, slice ); \ |
|||
\ |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|||
} |
|||
EvalShadow_CascadedDepth_( SamplerComparisonState ) |
|||
EvalShadow_CascadedDepth_( SamplerState ) |
|||
#undef EvalShadow_CascadedDepth_ |
|
|||
fileFormatVersion: 2 |
|||
guid: e2ca1e297ddf0b54f9d72244a419844b |
|||
timeCreated: 1491321445 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: aa4f463e1cdf08f42934e66c91cd612e |
|||
timeCreated: 1491321444 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 46258e7f416004a4db9dc7cc2c5a3b62 |
|||
timeCreated: 1491321444 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 870dbce0ad39569448fa01659ed39fd0 |
|||
timeCreated: 1491321444 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// This file contains various helper declarations for declaring and sampling members of the ShadowContext struct. |
|||
|
|||
// shadow lookup routines when dynamic array access is possible |
|||
#if SHADOW_SUPPORTS_DYNAMIC_INDEXING != 0 |
|||
|
|||
// Shader model >= 5.1 |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots , _SamplerCompSlots ) float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice ) { return SAMPLE_TEXTURE2D_ARRAY_SHADOW( ctxt.tex2DArray[texIdx], ctxt.compSamplers[sampIdx], tcs, slice ); } |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots , _SamplerSlots ) float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 ) { return SAMPLE_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[texIdx], ctxt.samplers[sampIdx], tcs, slice, lod ); } |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx ) { return SAMPLE_TEXTURECUBE_ARRAY_SHADOW( ctxt.texCubeArray[texIdx], ctxt.compSamplers[sampIdx], tcs, cubeIdx );} |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 ) { return SAMPLE_TEXTURECUBE_ARRAY_LOD( ctxt.texCubeArray[texIdx], ctxt.samplers[sampIdx], tcs, cubeIdx, lod ); } |
|||
|
|||
#else // helper macros if dynamic indexing does not work |
|||
|
|||
// Sampler and texture combinations are static. No shadowmap will ever be sampled with two different samplers. |
|||
// Once shadowmaps and samplers are fixed consider writing custom dispatchers directly accessing textures and samplers. |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots, _SamplerCompSlots ) \ |
|||
float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice ) \ |
|||
{ \ |
|||
float4 res = 1.0.xxxx; \ |
|||
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \ |
|||
{ \ |
|||
[unroll] for( uint j = 0; j < _SamplerCompSlots; j++ ) \ |
|||
{ \ |
|||
[branch] if( i == texIdx && j == sampIdx ) \ |
|||
{ \ |
|||
res = SAMPLE_TEXTURE2D_ARRAY_SHADOW( ctxt.tex2DArray[i], ctxt.compSamplers[j], tcs, slice ); \ |
|||
break; \ |
|||
} \ |
|||
} \ |
|||
} \ |
|||
return res; \ |
|||
} |
|||
|
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots, _SamplerSlots ) \ |
|||
float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 ) \ |
|||
{ \ |
|||
float4 res = 1.0.xxxx; \ |
|||
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \ |
|||
{ \ |
|||
[unroll] for( uint j = 0; j < _SamplerSlots; j++ ) \ |
|||
{ \ |
|||
[branch] if( i == texIdx && j == sampIdx ) \ |
|||
{ \ |
|||
res = SAMPLE_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[i], ctxt.samplers[j], tcs, slice, lod ); \ |
|||
break; \ |
|||
} \ |
|||
} \ |
|||
} \ |
|||
return res; \ |
|||
} |
|||
|
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) \ |
|||
float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx ) \ |
|||
{ \ |
|||
float4 res = 1.0.xxxx; \ |
|||
[unroll] for( uint i = 0; i < _TexCubeArraySlots; i++ ) \ |
|||
{ \ |
|||
[unroll] for( uint j = 0; j < _SamplerCompSlots; j++ ) \ |
|||
{ \ |
|||
[branch] if( i == texIdx && j == sampIdx ) \ |
|||
{ \ |
|||
res = SAMPLE_TEXTURECUBE_ARRAY_SHADOW( ctxt.texCubeArray[i], ctxt.compSamplers[j], tcs, cubeIdx ); \ |
|||
break; \ |
|||
} \ |
|||
} \ |
|||
} \ |
|||
return res; \ |
|||
} |
|||
|
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) \ |
|||
float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 ) \ |
|||
{ \ |
|||
float4 res = 1.0.xxxx; \ |
|||
[unroll] for( uint i = 0; i < _TexCubeArraySlots; i++ ) \ |
|||
{ \ |
|||
[unroll] for( uint j = 0; j < _SamplerSlots; j++ ) \ |
|||
{ \ |
|||
[branch] if( i == texIdx && j == sampIdx ) \ |
|||
{ \ |
|||
res = SAMPLE_TEXTURECUBE_ARRAY_LOD( ctxt.texCubeArray[i], ctxt.samplers[j], tcs, cubeIdx, lod ); \ |
|||
break; \ |
|||
} \ |
|||
} \ |
|||
} \ |
|||
return res; \ |
|||
} |
|||
#endif // SHADOW_SUPPORTS_DYNAMIC_INDEXING != 0 |
|||
|
|||
// helper macro to suppress code generation if _cnt is 0 |
|||
#define SHADOW_DECLARE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots , _SamplerCompSlots ) float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice ); |
|||
#define SHADOW_DECLARE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots , _SamplerSlots ) float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 ); |
|||
#define SHADOW_DECLARE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx ); |
|||
#define SHADOW_DECLARE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 ); |
|||
|
|||
#define SHADOW_CAT( _left, _right ) _left ## _right |
|||
|
|||
#define SHADOW_CHECK_0( _macro ) |
|||
#define SHADOW_CHECK_1( _macro ) _macro |
|||
#define SHADOW_CHECK_2( _macro ) _macro |
|||
#define SHADOW_CHECK_3( _macro ) _macro |
|||
#define SHADOW_CHECK_4( _macro ) _macro |
|||
#define SHADOW_CHECK_5( _macro ) _macro |
|||
#define SHADOW_CHECK_6( _macro ) _macro |
|||
#define SHADOW_CHECK_7( _macro ) _macro |
|||
#define SHADOW_CHECK_8( _macro ) _macro |
|||
#define SHADOW_CHECK_9( _macro ) _macro |
|||
#define SHADOW_CHECK( _cnt, _macro ) SHADOW_CAT( SHADOW_CHECK_ , _cnt ) ( _macro ) |
|||
|
|||
|
|||
#define SHADOW_CHECK_ALT_0( _macro, _alt ) _alt |
|||
#define SHADOW_CHECK_ALT_1( _macro, _alt ) _macro |
|||
#define SHADOW_CHECK_ALT_2( _macro, _alt ) _macro |
|||
#define SHADOW_CHECK_ALT_3( _macro, _alt ) _macro |
|||
#define SHADOW_CHECK_ALT_4( _macro, _alt ) _macro |
|||
#define SHADOW_CHECK_ALT_5( _macro, _alt ) _macro |
|||
#define SHADOW_CHECK_ALT_6( _macro, _alt ) _macro |
|||
#define SHADOW_CHECK_ALT_7( _macro, _alt ) _macro |
|||
#define SHADOW_CHECK_ALT_8( _macro, _alt ) _macro |
|||
#define SHADOW_CHECK_ALT_9( _macro, _alt ) _macro |
|||
#define SHADOW_CHECK_ALT( _cnt, _macro, _alt ) SHADOW_CAT( SHADOW_CHECK_ALT_ , _cnt ) ( _macro, _alt ) |
|||
|
|||
// helper macro to declare texture members for the shadow context. |
|||
#define SHADOWCONTEXT_DECLARE_TEXTURES( _Tex2DArraySlots, _TexCubeArraySlots, _SamplerCompSlots, _SamplerSlots ) \ |
|||
SHADOW_CHECK( _Tex2DArraySlots , Texture2DArray tex2DArray[_Tex2DArraySlots]; ) \ |
|||
SHADOW_CHECK( _TexCubeArraySlots, TextureCubeArray texCubeArray[_TexCubeArraySlots]; ) \ |
|||
SHADOW_CHECK( _SamplerCompSlots , SamplerComparisonState compSamplers[_Tex2DArraySlots]; ) \ |
|||
SHADOW_CHECK( _SamplerSlots , SamplerState samplers[_Tex2DArraySlots]; ) |
|||
// helper macro to declare texture sampling functions for the shadow context. |
|||
#define SHADOW_DEFINE_SAMPLING_FUNCS( _Tex2DArraySlots, _TexCubeArraySlots, _SamplerCompSlots, _SamplerSlots ) \ |
|||
SHADOW_CHECK( _Tex2DArraySlots , SHADOW_CHECK_ALT( _SamplerCompSlots, SHADOW_DEFINE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots, _SamplerCompSlots ), SHADOW_DECLARE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots, _SamplerCompSlots ) ) ) \ |
|||
SHADOW_CHECK( _Tex2DArraySlots , SHADOW_CHECK_ALT( _SamplerSlots , SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots, _SamplerSlots ), SHADOW_DECLARE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots, _SamplerSlots ) ) ) \ |
|||
SHADOW_CHECK( _TexCubeArraySlots, SHADOW_CHECK_ALT( _SamplerCompSlots, SHADOW_DEFINE_SAMPLING_FUNC_TCA_COMP(_TexCubeArraySlots, _SamplerCompSlots ), SHADOW_DECLARE_SAMPLING_FUNC_TCA_COMP(_TexCubeArraySlots, _SamplerCompSlots ) ) ) \ |
|||
SHADOW_CHECK( _TexCubeArraySlots, SHADOW_CHECK_ALT( _SamplerSlots , SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP(_TexCubeArraySlots, _SamplerSlots ), SHADOW_DECLARE_SAMPLING_FUNC_TCA_SAMP(_TexCubeArraySlots, _SamplerSlots ) ) ) |
|
|||
fileFormatVersion: 2 |
|||
guid: a9c17fbca36dfb744b42fb48d3829887 |
|||
timeCreated: 1491321444 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 11e59a3cb6482b245b20ac498cb3afd5 |
|||
timeCreated: 1491321441 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 78929777594e2d84aba05af5bf6463d0 |
|||
timeCreated: 1491321444 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 7640004f9f444ad40aba7003ccb31e7f |
|||
timeCreated: 1491321441 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public class ShadowUtilsConstants |
|||
{ |
|||
// Matches ScriptableShadowsUtility.cpp
|
|||
public enum CubemapEdge |
|||
{ |
|||
kCubeEdgePX_PY = 0, |
|||
kCubeEdgePX_NY, |
|||
kCubeEdgePX_PZ, |
|||
kCubeEdgePX_NZ, |
|||
|
|||
kCubeEdgeNX_PY, |
|||
kCubeEdgeNX_NY, |
|||
kCubeEdgeNX_PZ, |
|||
kCubeEdgeNX_NZ, |
|||
|
|||
kCubeEdgePY_PZ, |
|||
kCubeEdgePY_NZ, |
|||
kCubeEdgeNY_PZ, |
|||
kCubeEdgeNY_NZ, |
|||
kCubeEdge_Count |
|||
}; |
|||
|
|||
public static readonly CubemapEdge[,] kCubemapEdgesPerFace = new CubemapEdge[6,4] |
|||
{ |
|||
{ CubemapEdge.kCubeEdgePX_PY, CubemapEdge.kCubeEdgePX_NY, CubemapEdge.kCubeEdgePX_PZ, CubemapEdge.kCubeEdgePX_NZ }, // PX
|
|||
{ CubemapEdge.kCubeEdgeNX_PY, CubemapEdge.kCubeEdgeNX_NY, CubemapEdge.kCubeEdgeNX_PZ, CubemapEdge.kCubeEdgeNX_NZ }, // NX
|
|||
{ CubemapEdge.kCubeEdgePX_PY, CubemapEdge.kCubeEdgeNX_PY, CubemapEdge.kCubeEdgePY_PZ, CubemapEdge.kCubeEdgePY_NZ }, // PY
|
|||
{ CubemapEdge.kCubeEdgePX_NY, CubemapEdge.kCubeEdgeNX_NY, CubemapEdge.kCubeEdgeNY_PZ, CubemapEdge.kCubeEdgeNY_NZ }, // NY
|
|||
{ CubemapEdge.kCubeEdgePX_PZ, CubemapEdge.kCubeEdgeNX_PZ, CubemapEdge.kCubeEdgePY_PZ, CubemapEdge.kCubeEdgeNY_PZ }, // PZ
|
|||
{ CubemapEdge.kCubeEdgePX_NZ, CubemapEdge.kCubeEdgeNX_NZ, CubemapEdge.kCubeEdgePY_NZ, CubemapEdge.kCubeEdgeNY_NZ } // NZ
|
|||
}; |
|||
|
|||
const float oneOverSqr2 = 0.70710678118654752440084436210485f; |
|||
public static readonly Vector3[] kCubemapEdgeDirections = new Vector3[(int)CubemapEdge.kCubeEdge_Count] |
|||
{ |
|||
new Vector3( oneOverSqr2, oneOverSqr2, 0 ), |
|||
new Vector3( oneOverSqr2, -oneOverSqr2, 0 ), |
|||
new Vector3( oneOverSqr2, 0, oneOverSqr2 ), |
|||
new Vector3( oneOverSqr2, 0, -oneOverSqr2 ), |
|||
|
|||
new Vector3( -oneOverSqr2, oneOverSqr2, 0 ), |
|||
new Vector3( -oneOverSqr2, -oneOverSqr2, 0 ), |
|||
new Vector3( -oneOverSqr2, 0, oneOverSqr2 ), |
|||
new Vector3( -oneOverSqr2, 0, -oneOverSqr2 ), |
|||
|
|||
new Vector3( 0, oneOverSqr2, oneOverSqr2 ), |
|||
new Vector3( 0, oneOverSqr2, -oneOverSqr2 ), |
|||
new Vector3( 0, -oneOverSqr2, oneOverSqr2 ), |
|||
new Vector3( 0, -oneOverSqr2, -oneOverSqr2 ) |
|||
}; |
|||
|
|||
// Cubemap faces with flipped z coordinate.
|
|||
// These matrices do NOT match what we have in Skybox.cpp.
|
|||
// The C++ runtime flips y as well and requires patching up
|
|||
// the culling state. Using these matrices keeps the winding
|
|||
// order, but may need some special treatment if rendering
|
|||
// into an actual cubemap.
|
|||
public static readonly Matrix4x4[] kCubemapFaces = new Matrix4x4[] |
|||
{ |
|||
new Matrix4x4( // pos X
|
|||
new Vector4( 0.0f, 0.0f, -1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( -1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // neg x
|
|||
new Vector4( 0.0f, 0.0f, 1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // pos y
|
|||
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, -1.0f, 0.0f ), |
|||
new Vector4( 0.0f, -1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // neg y
|
|||
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // pos z
|
|||
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, -1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // neg z
|
|||
new Vector4( -1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ) |
|||
}; |
|||
|
|||
|
|||
|
|||
} |
|||
public class ShadowUtils |
|||
{ |
|||
public static Matrix4x4 ExtractSpotLightMatrix( VisibleLight vl, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData ) |
|||
{ |
|||
splitData = new ShadowSplitData(); |
|||
splitData.cullingSphere.Set( 0.0f, 0.0f, 0.0f, float.NegativeInfinity ); |
|||
splitData.cullingPlaneCount = 0; |
|||
// get lightDir
|
|||
lightDir = vl.light.transform.forward; |
|||
// calculate view
|
|||
Matrix4x4 scaleMatrix = Matrix4x4.identity; |
|||
scaleMatrix.m22 = -1.0f; |
|||
view = scaleMatrix * vl.localToWorld.inverse; |
|||
// following code is from SharedLightData::GetNearPlaneMinBound
|
|||
float percentageBound = 0.01f * vl.light.range; |
|||
float fixedBound = 0.1f; |
|||
float nearmin = fixedBound <= percentageBound ? fixedBound : percentageBound; |
|||
// calculate projection
|
|||
float zfar = vl.range; |
|||
float znear = vl.light.shadowNearPlane >= nearmin ? vl.light.shadowNearPlane : nearmin; |
|||
float fov = vl.spotAngle; |
|||
proj = Matrix4x4.Perspective(fov, 1.0f, znear, zfar); |
|||
// and the compound
|
|||
return proj * view; |
|||
} |
|||
|
|||
|
|||
public static Matrix4x4 ExtractPointLightMatrix( VisibleLight vl, uint faceIdx, float fovBias, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData ) |
|||
{ |
|||
Debug.Assert( faceIdx <= (uint) CubemapFace.NegativeZ, "Tried to extract cubemap face " + faceIdx + "." ); |
|||
|
|||
splitData = new ShadowSplitData(); |
|||
splitData.cullingSphere.Set( 0.0f, 0.0f, 0.0f, float.NegativeInfinity ); |
|||
splitData.cullingPlaneCount = 4; |
|||
// get lightDir
|
|||
lightDir = vl.light.transform.forward; |
|||
// calculate the view matrices
|
|||
Vector3 lpos = vl.light.transform.position; |
|||
view = ShadowUtilsConstants.kCubemapFaces[faceIdx]; |
|||
Vector3 inverted_viewpos = ShadowUtilsConstants.kCubemapFaces[faceIdx].MultiplyPoint( -lpos ); |
|||
view.SetColumn( 3, new Vector4( inverted_viewpos.x, inverted_viewpos.y, inverted_viewpos.z, 1.0f ) ); |
|||
|
|||
for( int i = 0; i < 4; ++i ) |
|||
{ |
|||
ShadowUtilsConstants.CubemapEdge cubemapEdge = ShadowUtilsConstants.kCubemapEdgesPerFace[faceIdx,i]; |
|||
Vector3 cullingPlaneDirection = ShadowUtilsConstants.kCubemapEdgeDirections[(int)cubemapEdge]; |
|||
splitData.SetCullingPlane( i, new Plane( cullingPlaneDirection, lpos ) ); |
|||
} |
|||
// following code is from SharedLightData::GetNearPlaneMinBound
|
|||
float percentageBound = 0.01f * vl.light.range; |
|||
float fixedBound = 0.1f; |
|||
float nearmin = fixedBound <= percentageBound ? fixedBound : percentageBound; |
|||
// calculate projection
|
|||
float farPlane = vl.range; |
|||
float nearPlane = vl.light.shadowNearPlane >= nearmin ? vl.light.shadowNearPlane : nearmin; |
|||
proj = Matrix4x4.Perspective( 90.0f + fovBias, 1.0f, nearPlane, farPlane ); |
|||
// and the compound
|
|||
return proj * view; |
|||
} |
|||
|
|||
public static Matrix4x4 ExtractDirectionalLightMatrix( VisibleLight vl, uint cascadeIdx, int cascadeCount, Vector3 splitRatio, float nearPlaneOffset, uint width, uint height, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex ) |
|||
{ |
|||
Debug.Assert( width == height, "Currently the cascaded shadow mapping code requires square cascades." ); |
|||
splitData = new ShadowSplitData(); |
|||
splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity); |
|||
splitData.cullingPlaneCount = 0; |
|||
// get lightDir
|
|||
lightDir = vl.light.transform.forward; |
|||
// TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well
|
|||
// For directional lights shadow data is extracted from the cullResults, so that needs to be somehow provided here.
|
|||
// Check ScriptableShadowsUtility.cpp ComputeDirectionalShadowMatricesAndCullingPrimitives(...) for details.
|
|||
cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( lightIndex, (int) cascadeIdx, cascadeCount, splitRatio, (int) width, nearPlaneOffset, out view, out proj, out splitData ); |
|||
// and the compound
|
|||
return proj * view; |
|||
} |
|||
|
|||
public static bool MapLightType( LightArchetype la, LightType lt, out HDPipeline.GPULightType gputype, out GPUShadowType shadowtype ) |
|||
{ |
|||
switch( la ) |
|||
{ |
|||
case LightArchetype.Punctual : return MapLightType( lt, out gputype, out shadowtype ); |
|||
case LightArchetype.Rectangle : gputype = HDPipeline.GPULightType.Rectangle; shadowtype = GPUShadowType.Unknown; return true; |
|||
case LightArchetype.Line : gputype = HDPipeline.GPULightType.Line; shadowtype = GPUShadowType.Unknown; return true; |
|||
default : gputype = HDPipeline.GPULightType.Spot; shadowtype = GPUShadowType.Unknown; return false; // <- probably not what you want
|
|||
} |
|||
|
|||
} |
|||
public static bool MapLightType( LightType lt, out HDPipeline.GPULightType gputype, out GPUShadowType shadowtype ) |
|||
{ |
|||
switch( lt ) |
|||
{ |
|||
case LightType.Spot : gputype = HDPipeline.GPULightType.Spot; shadowtype = GPUShadowType.Spot; return true; |
|||
case LightType.Directional : gputype = HDPipeline.GPULightType.Directional; shadowtype = GPUShadowType.Directional; return true; |
|||
case LightType.Point : gputype = HDPipeline.GPULightType.Point; shadowtype = GPUShadowType.Point; return true; |
|||
default: |
|||
case LightType.Area : gputype = HDPipeline.GPULightType.Rectangle; shadowtype = GPUShadowType.Unknown; return false; // area lights by themselves can't be mapped to any GPU type
|
|||
} |
|||
} |
|||
public static bool MapLightType(LightArchetype la, LightType lt, out GPUShadowType shadowtype) |
|||
{ |
|||
switch (la) |
|||
{ |
|||
case LightArchetype.Punctual: |
|||
return MapLightType(lt, out shadowtype); |
|||
case LightArchetype.Rectangle: |
|||
shadowtype = GPUShadowType.Unknown; |
|||
return true; |
|||
case LightArchetype.Line: |
|||
shadowtype = GPUShadowType.Unknown; |
|||
return true; |
|||
default: |
|||
shadowtype = GPUShadowType.Unknown; |
|||
return false; // <- probably not what you want
|
|||
} |
|||
|
|||
} |
|||
public static bool MapLightType(LightType lt, out GPUShadowType shadowtype) |
|||
{ |
|||
switch (lt) |
|||
{ |
|||
case LightType.Spot: |
|||
shadowtype = GPUShadowType.Spot; |
|||
return true; |
|||
case LightType.Directional: |
|||
shadowtype = GPUShadowType.Directional; |
|||
return true; |
|||
case LightType.Point: |
|||
shadowtype = GPUShadowType.Point; |
|||
return true; |
|||
default: |
|||
case LightType.Area: |
|||
shadowtype = GPUShadowType.Unknown; |
|||
return false; // area lights by themselves can't be mapped to any GPU type
|
|||
} |
|||
} |
|||
|
|||
public static GPUShadowAlgorithm Pack( ShadowAlgorithm algo, ShadowVariant vari, ShadowPrecision prec ) |
|||
{ |
|||
int precshift = ShadowExp.ShadowConstants.Bits.k_ShadowVariant + ShadowExp.ShadowConstants.Bits.k_ShadowAlgorithm; |
|||
int algoshift = ShadowExp.ShadowConstants.Bits.k_ShadowVariant; |
|||
return (GPUShadowAlgorithm) ( (int) prec << precshift | ((int) algo << algoshift) | (int)vari); |
|||
} |
|||
public static ShadowAlgorithm ExtractAlgorithm( GPUShadowAlgorithm gpuAlgo ) { return (ShadowAlgorithm) ( ShadowExp.ShadowConstants.Masks.k_ShadowAlgorithm & ((int)gpuAlgo >> ShadowExp.ShadowConstants.Bits.k_ShadowVariant) ); } |
|||
public static ShadowVariant ExtractVariant( GPUShadowAlgorithm gpuAlgo ) { return (ShadowVariant ) ( ShadowExp.ShadowConstants.Masks.k_ShadowVariant & (int)gpuAlgo ); } |
|||
public static ShadowPrecision ExtractPrecision( GPUShadowAlgorithm gpuAlgo ) { return (ShadowPrecision) ( ShadowExp.ShadowConstants.Masks.k_ShadowPrecision & ((int)gpuAlgo >> (ShadowExp.ShadowConstants.Bits.k_ShadowVariant + ShadowExp.ShadowConstants.Bits.k_ShadowAlgorithm)) ); } |
|||
public static void Unpack( GPUShadowAlgorithm gpuAlgo, out ShadowAlgorithm algo, out ShadowVariant vari, out ShadowPrecision prec ) |
|||
{ |
|||
algo = ExtractAlgorithm( gpuAlgo ); |
|||
vari = ExtractVariant( gpuAlgo ); |
|||
prec = ExtractPrecision( gpuAlgo ); |
|||
} |
|||
public static GPUShadowAlgorithm ClearPrecision( GPUShadowAlgorithm gpuAlgo ) |
|||
{ |
|||
var algo = ExtractAlgorithm( gpuAlgo ); |
|||
var vari = ExtractVariant( gpuAlgo ); |
|||
return Pack( algo, vari, ShadowPrecision.Low ); |
|||
} |
|||
public static float Asfloat( uint val ) { return System.BitConverter.ToSingle( System.BitConverter.GetBytes( val ), 0 ); } |
|||
public static float Asfloat( int val ) { return System.BitConverter.ToSingle( System.BitConverter.GetBytes( val ), 0 ); } |
|||
public static int Asint( float val ) { return System.BitConverter.ToInt32( System.BitConverter.GetBytes( val ), 0 ); } |
|||
public static uint Asuint( float val ) { return System.BitConverter.ToUInt32( System.BitConverter.GetBytes( val ), 0 ); } |
|||
} |
|||
} // end of namespace UnityEngine.Experimental.ScriptableRenderLoop
|
|
|||
fileFormatVersion: 2 |
|||
guid: d53d8bd422ecef740865c3acd7e2c62b |
|||
timeCreated: 1491321441 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: b6860f4fd5236f648b2c48c6799c68a7 |
|||
timeCreated: 1491321441 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 1c64d27a91e935140a9f402077f52fa0 |
|||
timeCreated: 1477395059 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 6931cfbd757a1864f8822b5399719960 |
|||
timeCreated: 1485511432 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 9900a5b8191991b4d9e2c37413d85dc3 |
|||
timeCreated: 1485511902 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 1163a3730c1812748b5cc5a7ecfbaf0c |
|||
timeCreated: 1485511901 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 68d59da52ffb57240bdf73300a2736bf |
|||
timeCreated: 1485788693 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 0998db889743f994b8ea4257f9ab33fa |
|||
timeCreated: 1485511431 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 4091aef5166b0624db069f6dbfd0673a |
|||
timeCreated: 1485511901 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 1c09a112d6337c7468843f1d64d7795f |
|||
timeCreated: 1485511901 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// This file contains various helper declarations for declaring and sampling members of the ShadowContext struct. |
|||
|
|||
// shadow lookup routines when dynamic array access is possible |
|||
#if SHADOW_SUPPORTS_DYNAMIC_INDEXING != 0 |
|||
|
|||
// Shader model >= 5.1 |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots , _SamplerCompSlots ) float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice ) { return SAMPLE_TEXTURE2D_ARRAY_SHADOW( ctxt.tex2DArray[texIdx], ctxt.compSamplers[sampIdx], tcs, slice ); } |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots , _SamplerSlots ) float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 ) { return SAMPLE_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[texIdx], ctxt.samplers[sampIdx], tcs, slice, lod ); } |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx ) { return SAMPLE_TEXTURECUBE_ARRAY_SHADOW( ctxt.texCubeArray[texIdx], ctxt.compSamplers[sampIdx], tcs, cubeIdx );} |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 ) { return SAMPLE_TEXTURECUBE_ARRAY_LOD( ctxt.texCubeArray[texIdx], ctxt.samplers[sampIdx], tcs, cubeIdx, lod ); } |
|||
|
|||
#else // helper macros if dynamic indexing does not work |
|||
|
|||
// Sampler and texture combinations are static. No shadowmap will ever be sampled with two different samplers. |
|||
// Once shadowmaps and samplers are fixed consider writing custom dispatchers directly accessing textures and samplers. |
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots, _SamplerCompSlots ) \ |
|||
float4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float slice ) \ |
|||
{ \ |
|||
float4 res = 1.0.xxxx; \ |
|||
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \ |
|||
{ \ |
|||
[unroll] for( uint j = 0; j < _SamplerCompSlots; j++ ) \ |
|||
{ \ |
|||
[branch] if( i == texIdx && j == sampIdx ) \ |
|||
{ \ |
|||
res = SAMPLE_TEXTURE2D_ARRAY_SHADOW( ctxt.tex2DArray[i], ctxt.compSamplers[j], tcs, slice ); \ |
|||
break; \ |
|||
} \ |
|||
} \ |
|||
} \ |
|||
return res; \ |
|||
} |
|||
|
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots, _SamplerSlots ) \ |
|||
float4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, float2 tcs, float slice, float lod = 0.0 ) \ |
|||
{ \ |
|||
float4 res = 1.0.xxxx; \ |
|||
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \ |
|||
{ \ |
|||
[unroll] for( uint j = 0; j < _SamplerSlots; j++ ) \ |
|||
{ \ |
|||
[branch] if( i == texIdx && j == sampIdx ) \ |
|||
{ \ |
|||
res = SAMPLE_TEXTURE2D_ARRAY_LOD( ctxt.tex2DArray[i], ctxt.samplers[j], tcs, slice, lod ); \ |
|||
break; \ |
|||
} \ |
|||
} \ |
|||
} \ |
|||
return res; \ |
|||
} |
|||
|
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_COMP( _TexCubeArraySlots, _SamplerCompSlots ) \ |
|||
float4 SampleCompShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float4 tcs, float cubeIdx ) \ |
|||
{ \ |
|||
float4 res = 1.0.xxxx; \ |
|||
[unroll] for( uint i = 0; i < _TexCubeArraySlots; i++ ) \ |
|||
{ \ |
|||
[unroll] for( uint j = 0; j < _SamplerCompSlots; j++ ) \ |
|||
{ \ |
|||
[branch] if( i == texIdx && j == sampIdx ) \ |
|||
{ \ |
|||
res = SAMPLE_TEXTURECUBE_ARRAY_SHADOW( ctxt.texCubeArray[i], ctxt.compSamplers[j], tcs, cubeIdx ); \ |
|||
break; \ |
|||
} \ |
|||
} \ |
|||
} \ |
|||
return res; \ |
|||
} |
|||
|
|||
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) \ |
|||
float4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, float3 tcs, float cubeIdx, float lod = 0.0 ) \ |
|||
{ \ |
|||
float4 res = 1.0.xxxx; \ |
|||
[unroll] for( uint i = 0; i < _TexCubeArraySlots; i++ ) \ |
|||
{ \ |
|||
[unroll] for( uint j = 0; j < _SamplerSlots; j++ ) \ |
|||
{ \ |
|||
[branch] if( i == texIdx && j == sampIdx ) \ |
|||
{ \ |
|||
res = SAMPLE_TEXTURECUBE_ARRAY_LOD( ctxt.texCubeArray[i], ctxt.samplers[j], tcs, cubeIdx, lod ); \ |
|||
break; \ |
|||
} \ |
|||
} \ |
|||
} \ |
|||
return res; \ |
|||
} |
|||
#endif // SHADOW_SUPPORTS_DYNAMIC_INDEXING != 0 |
|||
|
|||
|
|||
// helper macro to suppress code generation if _cnt is 0 |
|||
#define SHADOW_CHECK_0( _macro ) |
|||
#define SHADOW_CHECK_1( _macro ) _macro |
|||
#define SHADOW_CHECK_2( _macro ) _macro |
|||
#define SHADOW_CHECK_3( _macro ) _macro |
|||
#define SHADOW_CHECK_4( _macro ) _macro |
|||
#define SHADOW_CHECK_5( _macro ) _macro |
|||
#define SHADOW_CHECK_6( _macro ) _macro |
|||
#define SHADOW_CHECK_7( _macro ) _macro |
|||
#define SHADOW_CHECK_8( _macro ) _macro |
|||
#define SHADOW_CHECK_9( _macro ) _macro |
|||
#define SHADOW_CHECK( _cnt, _macro ) MERGE_NAME( SHADOW_CHECK_ , _cnt ) ( _macro ) |
|||
|
|||
// helper macro to declare texture members for the shadow context. |
|||
#define SHADOWCONTEXT_DECLARE_TEXTURES( _Tex2DArraySlots, _TexCubeArraySlots, _SamplerCompSlots, _SamplerSlots ) \ |
|||
SHADOW_CHECK( _Tex2DArraySlots , Texture2DArray tex2DArray[_Tex2DArraySlots]; ) \ |
|||
SHADOW_CHECK( _TexCubeArraySlots, TextureCubeArray texCubeArray[_Tex2DArraySlots]; ) \ |
|||
SHADOW_CHECK( _SamplerCompSlots , SamplerComparisonState compSamplers[_Tex2DArraySlots]; ) \ |
|||
SHADOW_CHECK( _SamplerSlots , SamplerState samplers[_Tex2DArraySlots]; ) |
|||
// helper macro to declare texture sampling functions for the shadow context. |
|||
#define SHADOW_DEFINE_SAMPLING_FUNCS( _Tex2DArraySlots, _TexCubeArraySlots, _SamplerCompSlots, _SamplerSlots ) \ |
|||
SHADOW_CHECK( _Tex2DArraySlots , SHADOW_CHECK( _SamplerCompSlots, SHADOW_DEFINE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots, _SamplerCompSlots ) ) ) \ |
|||
SHADOW_CHECK( _Tex2DArraySlots , SHADOW_CHECK( _SamplerSlots , SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots, _SamplerSlots ) ) ) \ |
|||
SHADOW_CHECK( _TexCubeArraySlots, SHADOW_CHECK( _SamplerCompSlots, SHADOW_DEFINE_SAMPLING_FUNC_TCA_COMP(_TexCubeArraySlots, _SamplerCompSlots ) ) ) \ |
|||
SHADOW_CHECK( _TexCubeArraySlots, SHADOW_CHECK( _SamplerSlots , SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP(_TexCubeArraySlots, _SamplerSlots ) ) ) |
|
|||
fileFormatVersion: 2 |
|||
guid: 2ac0d1cc115e6ec42b5c47d2ee13f139 |
|||
timeCreated: 1485873843 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
|
|||
namespace UnityEngine.Experimental.Rendering.HDPipeline |
|||
{ |
|||
public class ShadowUtilsConstants |
|||
{ |
|||
// Matches ScriptableShadowsUtility.cpp
|
|||
public enum CubemapEdge |
|||
{ |
|||
kCubeEdgePX_PY = 0, |
|||
kCubeEdgePX_NY, |
|||
kCubeEdgePX_PZ, |
|||
kCubeEdgePX_NZ, |
|||
|
|||
kCubeEdgeNX_PY, |
|||
kCubeEdgeNX_NY, |
|||
kCubeEdgeNX_PZ, |
|||
kCubeEdgeNX_NZ, |
|||
|
|||
kCubeEdgePY_PZ, |
|||
kCubeEdgePY_NZ, |
|||
kCubeEdgeNY_PZ, |
|||
kCubeEdgeNY_NZ, |
|||
kCubeEdge_Count |
|||
}; |
|||
|
|||
public static readonly CubemapEdge[,] kCubemapEdgesPerFace = new CubemapEdge[6,4] |
|||
{ |
|||
{ CubemapEdge.kCubeEdgePX_PY, CubemapEdge.kCubeEdgePX_NY, CubemapEdge.kCubeEdgePX_PZ, CubemapEdge.kCubeEdgePX_NZ }, // PX
|
|||
{ CubemapEdge.kCubeEdgeNX_PY, CubemapEdge.kCubeEdgeNX_NY, CubemapEdge.kCubeEdgeNX_PZ, CubemapEdge.kCubeEdgeNX_NZ }, // NX
|
|||
{ CubemapEdge.kCubeEdgePX_PY, CubemapEdge.kCubeEdgeNX_PY, CubemapEdge.kCubeEdgePY_PZ, CubemapEdge.kCubeEdgePY_NZ }, // PY
|
|||
{ CubemapEdge.kCubeEdgePX_NY, CubemapEdge.kCubeEdgeNX_NY, CubemapEdge.kCubeEdgeNY_PZ, CubemapEdge.kCubeEdgeNY_NZ }, // NY
|
|||
{ CubemapEdge.kCubeEdgePX_PZ, CubemapEdge.kCubeEdgeNX_PZ, CubemapEdge.kCubeEdgePY_PZ, CubemapEdge.kCubeEdgeNY_PZ }, // PZ
|
|||
{ CubemapEdge.kCubeEdgePX_NZ, CubemapEdge.kCubeEdgeNX_NZ, CubemapEdge.kCubeEdgePY_NZ, CubemapEdge.kCubeEdgeNY_NZ } // NZ
|
|||
}; |
|||
|
|||
const float oneOverSqr2 = 0.70710678118654752440084436210485f; |
|||
public static readonly Vector3[] kCubemapEdgeDirections = new Vector3[(int)CubemapEdge.kCubeEdge_Count] |
|||
{ |
|||
new Vector3( oneOverSqr2, oneOverSqr2, 0 ), |
|||
new Vector3( oneOverSqr2, -oneOverSqr2, 0 ), |
|||
new Vector3( oneOverSqr2, 0, oneOverSqr2 ), |
|||
new Vector3( oneOverSqr2, 0, -oneOverSqr2 ), |
|||
|
|||
new Vector3( -oneOverSqr2, oneOverSqr2, 0 ), |
|||
new Vector3( -oneOverSqr2, -oneOverSqr2, 0 ), |
|||
new Vector3( -oneOverSqr2, 0, oneOverSqr2 ), |
|||
new Vector3( -oneOverSqr2, 0, -oneOverSqr2 ), |
|||
|
|||
new Vector3( 0, oneOverSqr2, oneOverSqr2 ), |
|||
new Vector3( 0, oneOverSqr2, -oneOverSqr2 ), |
|||
new Vector3( 0, -oneOverSqr2, oneOverSqr2 ), |
|||
new Vector3( 0, -oneOverSqr2, -oneOverSqr2 ) |
|||
}; |
|||
|
|||
// Cubemap faces with flipped z coordinate.
|
|||
// These matrices do NOT match what we have in Skybox.cpp.
|
|||
// The C++ runtime flips y as well and requires patching up
|
|||
// the culling state. Using these matrices keeps the winding
|
|||
// order, but may need some special treatment if rendering
|
|||
// into an actual cubemap.
|
|||
public static readonly Matrix4x4[] kCubemapFaces = new Matrix4x4[] |
|||
{ |
|||
new Matrix4x4( // pos X
|
|||
new Vector4( 0.0f, 0.0f, -1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( -1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // neg x
|
|||
new Vector4( 0.0f, 0.0f, 1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // pos y
|
|||
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, -1.0f, 0.0f ), |
|||
new Vector4( 0.0f, -1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // neg y
|
|||
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // pos z
|
|||
new Vector4( 1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, -1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ), |
|||
new Matrix4x4( // neg z
|
|||
new Vector4( -1.0f, 0.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 1.0f, 0.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 1.0f, 0.0f ), |
|||
new Vector4( 0.0f, 0.0f, 0.0f, 1.0f ) ) |
|||
}; |
|||
|
|||
|
|||
|
|||
} |
|||
public class ShadowUtils |
|||
{ |
|||
public static Matrix4x4 ExtractSpotLightMatrix( VisibleLight vl, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData ) |
|||
{ |
|||
splitData = new ShadowSplitData(); |
|||
splitData.cullingSphere.Set( 0.0f, 0.0f, 0.0f, float.NegativeInfinity ); |
|||
splitData.cullingPlaneCount = 0; |
|||
// get lightDir
|
|||
lightDir = vl.light.transform.forward; |
|||
// calculate view
|
|||
Matrix4x4 scaleMatrix = Matrix4x4.identity; |
|||
scaleMatrix.m22 = -1.0f; |
|||
view = scaleMatrix * vl.localToWorld.inverse; |
|||
// following code is from SharedLightData::GetNearPlaneMinBound
|
|||
float percentageBound = 0.01f * vl.light.range; |
|||
float fixedBound = 0.1f; |
|||
float nearmin = fixedBound <= percentageBound ? fixedBound : percentageBound; |
|||
// calculate projection
|
|||
float zfar = vl.range; |
|||
float znear = vl.light.shadowNearPlane >= nearmin ? vl.light.shadowNearPlane : nearmin; |
|||
float fov = vl.spotAngle; |
|||
proj = Matrix4x4.Perspective(fov, 1.0f, znear, zfar); |
|||
// and the compound
|
|||
return proj * view; |
|||
} |
|||
|
|||
|
|||
public static Matrix4x4 ExtractPointLightMatrix( VisibleLight vl, uint faceIdx, float fovBias, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData ) |
|||
{ |
|||
Debug.Assert( faceIdx <= (uint) CubemapFace.NegativeZ, "Tried to extract cubemap face " + faceIdx + "." ); |
|||
|
|||
splitData = new ShadowSplitData(); |
|||
splitData.cullingSphere.Set( 0.0f, 0.0f, 0.0f, float.NegativeInfinity ); |
|||
splitData.cullingPlaneCount = 4; |
|||
// get lightDir
|
|||
lightDir = vl.light.transform.forward; |
|||
// calculate the view matrices
|
|||
Vector3 lpos = vl.light.transform.position; |
|||
view = ShadowUtilsConstants.kCubemapFaces[faceIdx]; |
|||
Vector3 inverted_viewpos = ShadowUtilsConstants.kCubemapFaces[faceIdx].MultiplyPoint( -lpos ); |
|||
view.SetColumn( 3, new Vector4( inverted_viewpos.x, inverted_viewpos.y, inverted_viewpos.z, 1.0f ) ); |
|||
|
|||
for( int i = 0; i < 4; ++i ) |
|||
{ |
|||
ShadowUtilsConstants.CubemapEdge cubemapEdge = ShadowUtilsConstants.kCubemapEdgesPerFace[faceIdx,i]; |
|||
Vector3 cullingPlaneDirection = ShadowUtilsConstants.kCubemapEdgeDirections[(int)cubemapEdge]; |
|||
splitData.SetCullingPlane( i, new Plane( cullingPlaneDirection, lpos ) ); |
|||
} |
|||
// following code is from SharedLightData::GetNearPlaneMinBound
|
|||
float percentageBound = 0.01f * vl.light.range; |
|||
float fixedBound = 0.1f; |
|||
float nearmin = fixedBound <= percentageBound ? fixedBound : percentageBound; |
|||
// calculate projection
|
|||
float farPlane = vl.range; |
|||
float nearPlane = vl.light.shadowNearPlane >= nearmin ? vl.light.shadowNearPlane : nearmin; |
|||
proj = Matrix4x4.Perspective( 90.0f + fovBias, 1.0f, nearPlane, farPlane ); |
|||
// and the compound
|
|||
return proj * view; |
|||
} |
|||
|
|||
public static Matrix4x4 ExtractDirectionalLightMatrix( VisibleLight vl, uint cascadeIdx, int cascadeCount, Vector3 splitRatio, float nearPlaneOffset, uint width, uint height, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex ) |
|||
{ |
|||
Debug.Assert( width == height, "Currently the cascaded shadow mapping code requires square cascades." ); |
|||
splitData = new ShadowSplitData(); |
|||
splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity); |
|||
splitData.cullingPlaneCount = 0; |
|||
// get lightDir
|
|||
lightDir = vl.light.transform.forward; |
|||
// TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well
|
|||
// For directional lights shadow data is extracted from the cullResults, so that needs to be somehow provided here.
|
|||
// Check ScriptableShadowsUtility.cpp ComputeDirectionalShadowMatricesAndCullingPrimitives(...) for details.
|
|||
cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives( lightIndex, (int) cascadeIdx, cascadeCount, splitRatio, (int) width, nearPlaneOffset, out view, out proj, out splitData ); |
|||
// and the compound
|
|||
return proj * view; |
|||
} |
|||
|
|||
public static bool MapLightType( LightArchetype la, LightType lt, out GPULightType gputype, out GPUShadowType shadowtype ) |
|||
{ |
|||
switch( la ) |
|||
{ |
|||
case LightArchetype.Punctual : return MapLightType( lt, out gputype, out shadowtype ); |
|||
case LightArchetype.Rectangle : gputype = GPULightType.Rectangle; shadowtype = GPUShadowType.Unknown; return true; |
|||
case LightArchetype.Line : gputype = GPULightType.Line; shadowtype = GPUShadowType.Unknown; return true; |
|||
default : gputype = GPULightType.Spot; shadowtype = GPUShadowType.Unknown; return false; // <- probably not what you want
|
|||
} |
|||
|
|||
} |
|||
public static bool MapLightType( LightType lt, out GPULightType gputype, out GPUShadowType shadowtype ) |
|||
{ |
|||
switch( lt ) |
|||
{ |
|||
case LightType.Spot : gputype = GPULightType.Spot; shadowtype = GPUShadowType.Spot; return true; |
|||
case LightType.Directional : gputype = GPULightType.Directional; shadowtype = GPUShadowType.Directional; return true; |
|||
case LightType.Point : gputype = GPULightType.Point; shadowtype = GPUShadowType.Point; return true; |
|||
default: |
|||
case LightType.Area : gputype = GPULightType.Rectangle; shadowtype = GPUShadowType.Unknown; return false; // area lights by themselves can't be mapped to any GPU type
|
|||
} |
|||
} |
|||
public static GPUShadowAlgorithm Pack( ShadowAlgorithm algo, ShadowVariant vari, ShadowPrecision prec ) |
|||
{ |
|||
int precshift = ShadowExp.ShadowConstants.Bits.k_ShadowVariant + ShadowExp.ShadowConstants.Bits.k_ShadowAlgorithm; |
|||
int algoshift = ShadowExp.ShadowConstants.Bits.k_ShadowVariant; |
|||
return (GPUShadowAlgorithm) ( (int) prec << precshift | ((int) algo << algoshift) | (int)vari); |
|||
} |
|||
public static ShadowAlgorithm ExtractAlgorithm( GPUShadowAlgorithm gpuAlgo ) { return (ShadowAlgorithm) ( ShadowExp.ShadowConstants.Masks.k_ShadowAlgorithm & ((int)gpuAlgo >> ShadowExp.ShadowConstants.Bits.k_ShadowVariant) ); } |
|||
public static ShadowVariant ExtractVariant( GPUShadowAlgorithm gpuAlgo ) { return (ShadowVariant ) ( ShadowExp.ShadowConstants.Masks.k_ShadowVariant & (int)gpuAlgo ); } |
|||
public static ShadowPrecision ExtractPrecision( GPUShadowAlgorithm gpuAlgo ) { return (ShadowPrecision) ( ShadowExp.ShadowConstants.Masks.k_ShadowPrecision & ((int)gpuAlgo >> (ShadowExp.ShadowConstants.Bits.k_ShadowVariant + ShadowExp.ShadowConstants.Bits.k_ShadowAlgorithm)) ); } |
|||
public static void Unpack( GPUShadowAlgorithm gpuAlgo, out ShadowAlgorithm algo, out ShadowVariant vari, out ShadowPrecision prec ) |
|||
{ |
|||
algo = ExtractAlgorithm( gpuAlgo ); |
|||
vari = ExtractVariant( gpuAlgo ); |
|||
prec = ExtractPrecision( gpuAlgo ); |
|||
} |
|||
public static GPUShadowAlgorithm ClearPrecision( GPUShadowAlgorithm gpuAlgo ) |
|||
{ |
|||
var algo = ExtractAlgorithm( gpuAlgo ); |
|||
var vari = ExtractVariant( gpuAlgo ); |
|||
return Pack( algo, vari, ShadowPrecision.Low ); |
|||
} |
|||
public static float Asfloat( uint val ) { return System.BitConverter.ToSingle( System.BitConverter.GetBytes( val ), 0 ); } |
|||
public static float Asfloat( int val ) { return System.BitConverter.ToSingle( System.BitConverter.GetBytes( val ), 0 ); } |
|||
public static int Asint( float val ) { return System.BitConverter.ToInt32( System.BitConverter.GetBytes( val ), 0 ); } |
|||
public static uint Asuint( float val ) { return System.BitConverter.ToUInt32( System.BitConverter.GetBytes( val ), 0 ); } |
|||
} |
|||
} // end of namespace UnityEngine.Experimental.ScriptableRenderLoop
|
|
|||
fileFormatVersion: 2 |
|||
guid: 99dfd76ad655ff441aef9bb0015a1f05 |
|||
timeCreated: 1485511433 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: f5c1ec8ec44960d4bbf72eafaf47d8fd |
|||
timeCreated: 1485511435 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// Various shadow algorithms |
|||
// There are two variants provided, one takes the texture and sampler explicitly so they can be statically passed in. |
|||
// The variant without resource parameters dynamically accesses the texture when sampling. |
|||
|
|||
// Helper function to offset depth based on the surface normal and light direction. |
|||
// If the light hits the surface perpendicularly there will be no offset. |
|||
float3 EvalShadow_NormalBias( float3 normalWS, float NoL, float2 texelSize, float normalBias ) |
|||
{ |
|||
return max( texelSize.x, texelSize.y ) * normalBias * (1.0 - NoL) * normalWS; |
|||
} |
|||
|
|||
// function called by spot, point and directional eval routines to calculate shadow coordinates |
|||
float3 EvalShadow_GetTexcoords( ShadowData sd, float3 positionWS ) |
|||
{ |
|||
float4 posCS = mul( float4( positionWS, 1.0 ), sd.worldToShadow ); |
|||
posCS.z -= sd.bias * posCS.w; |
|||
float3 posNDC = posCS.xyz / posCS.w; |
|||
// calc TCs |
|||
float3 posTC = posNDC * 0.5 + 0.5; |
|||
posTC.xy = posTC.xy * sd.scaleOffset.xy + sd.scaleOffset.zw; |
|||
#if UNITY_REVERSED_Z |
|||
posTC.z = 1.0 - posTC.z; |
|||
#endif |
|||
return posTC; |
|||
} |
|||
|
|||
// |
|||
// Point shadows |
|||
// |
|||
float EvalShadow_PointDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L ) |
|||
{ |
|||
// load the right shadow data for the current face |
|||
int faceIndex = 0; |
|||
GetCubeFaceID( L, faceIndex ); |
|||
ShadowData sd = shadowContext.shadowDatas[index + 1 + faceIndex]; |
|||
uint payloadOffset = GetPayloadOffset( sd ); |
|||
// normal based bias |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); |
|||
// get shadowmap texcoords |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); |
|||
// get the algorithm |
|||
uint shadowType, shadowAlgorithm; |
|||
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|||
// sample the texture according to the given algorithm |
|||
uint texIdx, sampIdx; |
|||
float slice; |
|||
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx ); |
|||
} |
|||
|
|||
#define EvalShadow_PointDepth_( _samplerType ) \ |
|||
float EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \ |
|||
{ \ |
|||
/* load the right shadow data for the current face */ \ |
|||
int faceIndex = 0; \ |
|||
GetCubeFaceID( L, faceIndex ); \ |
|||
ShadowData sd = shadowContext.shadowDatas[index + 1 + faceIndex]; \ |
|||
uint payloadOffset = GetPayloadOffset( sd ); \ |
|||
/* normal based bias */ \ |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \ |
|||
/* get shadowmap texcoords */ \ |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|||
/* sample the texture */ \ |
|||
float slice; \ |
|||
UnpackShadowmapId( sd.id, slice ); \ |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|||
} |
|||
EvalShadow_PointDepth_( SamplerComparisonState ) |
|||
EvalShadow_PointDepth_( SamplerState ) |
|||
#undef EvalShadow_PointDepth_ |
|||
|
|||
// |
|||
// Spot shadows |
|||
// |
|||
float EvalShadow_SpotDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L ) |
|||
{ |
|||
// load the right shadow data for the current face |
|||
ShadowData sd = shadowContext.shadowDatas[index]; |
|||
uint payloadOffset = GetPayloadOffset( sd ); |
|||
// normal based bias |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); |
|||
// get shadowmap texcoords |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); |
|||
// get the algorithm |
|||
uint shadowType, shadowAlgorithm; |
|||
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|||
// sample the texture according to the given algorithm |
|||
uint texIdx, sampIdx; |
|||
float slice; |
|||
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx ); |
|||
} |
|||
|
|||
#define EvalShadow_SpotDepth_( _samplerType ) \ |
|||
float EvalShadow_SpotDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \ |
|||
{ \ |
|||
/* load the right shadow data for the current face */ \ |
|||
ShadowData sd = shadowContext.shadowDatas[index]; \ |
|||
uint payloadOffset = GetPayloadOffset( sd ); \ |
|||
/* normal based bias */ \ |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \ |
|||
/* get shadowmap texcoords */ \ |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|||
/* sample the texture */ \ |
|||
float slice; \ |
|||
UnpackShadowmapId( sd.id, slice ); \ |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|||
} |
|||
EvalShadow_SpotDepth_( SamplerComparisonState ) |
|||
EvalShadow_SpotDepth_( SamplerState ) |
|||
#undef EvalShadow_SpotDepth_ |
|||
|
|||
// |
|||
// Punctual shadows for Point and Spot |
|||
// |
|||
float EvalShadow_PunctualDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L ) |
|||
{ |
|||
// load the right shadow data for the current face |
|||
int faceIndex = 0; |
|||
// get the algorithm |
|||
uint shadowType, shadowAlgorithm; |
|||
UnpackShadowType( shadowContext.shadowDatas[index].shadowType, shadowType ); |
|||
|
|||
[branch] |
|||
if( shadowType == GPUSHADOWTYPE_POINT ) |
|||
{ |
|||
GetCubeFaceID( L, faceIndex ); |
|||
faceIndex++; |
|||
} |
|||
|
|||
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; |
|||
uint payloadOffset = GetPayloadOffset( sd ); |
|||
// normal based bias |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); |
|||
// get shadowmap texcoords |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); |
|||
// sample the texture according to the given algorithm |
|||
uint texIdx, sampIdx; |
|||
float slice; |
|||
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|||
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx ); |
|||
} |
|||
|
|||
#define EvalShadow_PunctualDepth_( _samplerType ) \ |
|||
float EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \ |
|||
{ \ |
|||
/* load the right shadow data for the current face */ \ |
|||
int faceIndex = 0; \ |
|||
/* get the shadow type */ \ |
|||
uint shadowType; \ |
|||
UnpackShadowType( shadowContext.shadowDatas[index].shadowType, shadowType ); \ |
|||
\ |
|||
[branch] \ |
|||
if( shadowType == GPUSHADOWTYPE_POINT ) \ |
|||
{ \ |
|||
GetCubeFaceID( L, faceIndex ); \ |
|||
faceIndex++; \ |
|||
} \ |
|||
\ |
|||
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; \ |
|||
uint payloadOffset = GetPayloadOffset( sd ); \ |
|||
/* normal based bias */ \ |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \ |
|||
/* get shadowmap texcoords */ \ |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|||
/* sample the texture */ \ |
|||
float slice; \ |
|||
UnpackShadowmapId( sd.id, slice ); \ |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|||
} |
|||
EvalShadow_PunctualDepth_( SamplerComparisonState ) |
|||
EvalShadow_PunctualDepth_( SamplerState ) |
|||
#undef EvalShadow_PunctualDepth_ |
|||
|
|||
// |
|||
// Directional shadows (cascaded shadow map) |
|||
// |
|||
int EvalShadow_GetSplitSphereIndexForDirshadows( float3 positionWS, float4 dirShadowSplitSpheres[4] ) |
|||
{ |
|||
float3 fromCenter0 = positionWS.xyz - dirShadowSplitSpheres[0].xyz; |
|||
float3 fromCenter1 = positionWS.xyz - dirShadowSplitSpheres[1].xyz; |
|||
float3 fromCenter2 = positionWS.xyz - dirShadowSplitSpheres[2].xyz; |
|||
float3 fromCenter3 = positionWS.xyz - dirShadowSplitSpheres[3].xyz; |
|||
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3)); |
|||
|
|||
float4 dirShadowSplitSphereSqRadii; |
|||
dirShadowSplitSphereSqRadii.x = dirShadowSplitSpheres[0].w; |
|||
dirShadowSplitSphereSqRadii.y = dirShadowSplitSpheres[1].w; |
|||
dirShadowSplitSphereSqRadii.z = dirShadowSplitSpheres[2].w; |
|||
dirShadowSplitSphereSqRadii.w = dirShadowSplitSpheres[3].w; |
|||
|
|||
if( distances2.w > dirShadowSplitSphereSqRadii.w ) |
|||
return -1; |
|||
|
|||
float4 weights = float4( distances2 < dirShadowSplitSphereSqRadii ); |
|||
weights.yzw = saturate( weights.yzw - weights.xyz ); |
|||
|
|||
return int( 4.0 - dot( weights, float4(4.0, 3.0, 2.0, 1.0 ) ) ); |
|||
} |
|||
|
|||
uint EvalShadow_LoadSplitSpheres( ShadowContext shadowContext, int index, out float4 splitSpheres[4] ) |
|||
{ |
|||
uint offset = GetPayloadOffset( shadowContext.shadowDatas[index] ); |
|||
|
|||
splitSpheres[0] = asfloat( shadowContext.payloads[offset + 0] ); |
|||
splitSpheres[1] = asfloat( shadowContext.payloads[offset + 1] ); |
|||
splitSpheres[2] = asfloat( shadowContext.payloads[offset + 2] ); |
|||
splitSpheres[3] = asfloat( shadowContext.payloads[offset + 3] ); |
|||
return offset + 4; |
|||
} |
|||
|
|||
float EvalShadow_CascadedDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L ) |
|||
{ |
|||
// load the right shadow data for the current face |
|||
float4 dirShadowSplitSpheres[4]; |
|||
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); |
|||
int shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres ); |
|||
if( shadowSplitIndex < 0 ) |
|||
return 1.0; |
|||
|
|||
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; |
|||
// normal based bias |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); |
|||
// get shadowmap texcoords |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); |
|||
|
|||
// sample the texture |
|||
uint texIdx, sampIdx; |
|||
float slice; |
|||
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|||
|
|||
uint shadowType, shadowAlgorithm; |
|||
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|||
|
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx ); |
|||
} |
|||
|
|||
#define EvalShadow_CascadedDepth_( _samplerType ) \ |
|||
float EvalShadow_CascadedDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \ |
|||
{ \ |
|||
/* load the right shadow data for the current face */ \ |
|||
float4 dirShadowSplitSpheres[4]; \ |
|||
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); \ |
|||
uint shadowSplitIndex = EvalShadow_GetSplitSphereIndexForDirshadows( positionWS, dirShadowSplitSpheres ); \ |
|||
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \ |
|||
/* normal based bias */ \ |
|||
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \ |
|||
/* get shadowmap texcoords */ \ |
|||
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|||
/* sample the texture */ \ |
|||
float slice; \ |
|||
UnpackShadowmapId( sd.id, slice ); \ |
|||
\ |
|||
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|||
} |
|||
EvalShadow_CascadedDepth_( SamplerComparisonState ) |
|||
EvalShadow_CascadedDepth_( SamplerState ) |
|||
#undef EvalShadow_CascadedDepth_ |
|
|||
fileFormatVersion: 2 |
|||
guid: 32c86a80860fd014ba44f8b7a7914a5c |
|||
timeCreated: 1487253249 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: fac04f0cf24b3844e8745273c0627fd1 |
|||
timeCreated: 1488300302 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 8450f392b53a9ef45b6f93b11a8d49af |
|||
folderAsset: yes |
|||
timeCreated: 1488205057 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue