You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
a466633b17
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3195953 on 2016/11/12 by Leslie.Nivison Rollback //UE4/Release-4.14/Engine/Plugins/Runtime/Nvidia to changelist 3193712 New GameWorks license from NVIDIA #jira UEPROD-900 Change 3195944 on 2016/11/12 by Leslie.Nivison Removing GameWorks SDK license until we get a new one from NVIDIA #jira UEPROD-900 Change 3195942 on 2016/11/11 by Chris.Gagnon Removing Ansel from 4.14 until revised EULA is handle. #jira UE-none Change 3195431 on 2016/11/11 by Mitchell.Wilson Rebuilt lighting in subway reflections sample #jira UE-38538 Change 3195080 on 2016/11/11 by mason.seay Extended floor to allow more driving space #jira UE-29618 Change 3194886 on 2016/11/11 by Chris.Babcock Correct handling for 6x6 blocksize in ASTC compressor #jira UE-38513 #ue4 #android Change 3193712 on 2016/11/10 by Leslie.Nivison Updating Ansel TPS info per NVIDIA response #jira UEPROD-900 Change 3193691 on 2016/11/10 by Lina.Halper #jira: UE-38488 Change 3193532 on 2016/11/10 by Lauren.Ridge Fix to keep the user in VR editing mode after leaving VR PIE. #jira UE-38317 Change 3193468 on 2016/11/10 by Leslie.Nivison Removing unneeded license #jira UEPROD-900 Change 3193465 on 2016/11/10 by Leslie.Nivison Updating credits for 4.14 #jira UEPROD-902 Change 3193416 on 2016/11/10 by Daniel.Lamb Changed default of exclude editor only content flag. #jira UE-38455 Change 3193399 on 2016/11/10 by Mitchell.Wilson Applied correct material to certain LODs of tree meshes in KiteDemo #jira UE-38472 Change 3193049 on 2016/11/10 by Thomas.Sarkanen Fix disappearing mesh on undo in skeletal mesh editor Also fixes crash on undo in morph target panel #jira UE-38430 - Undo in Skeletal Mesh Editor causes model to disappear #jira UE-38437 - Crash when Undo after editing a weight in Morph Target Previewer Change 3192655 on 2016/11/09 by Ryan.Vance #jira UE-37238 Pulling in 3164679 and 3169467 which didn't make the 4.14 cut. Also changed to a full inverse for InvTranslatedViewProjectionMatrix in FViewMatrices::UpdateViewMatrix. Change 3192613 on 2016/11/09 by Leslie.Nivison Updating licenses due to TPS version updates. Logging undocumented TPS per engine audit #jira UEPROD-900 Change 3192197 on 2016/11/09 by Daniel.Wright Added SUPPORT_CONTACT_SHADOWS, only standard deferred lighting supports it. Fixes scene depth texture bound in forward shading base pass. #jira UE-38340 Change 3192182 on 2016/11/09 by Rolando.Caloca UE4.14 - Fix recompute tangents not working when skin cache is enabled #jira UE-38398 Change3191695on 2016/11/09 by Chris.Wood Editor heartbeat changes for 4.14 [AN-1003] - Make Editor heartbeat 1min [UE-38417] - Editor heartbeat changes (vanilla editor, new interval, debugger attached) Also added IsDebugger, IsVanilla and IntervalSec to Editor.Usage.Heartbeat #jira UE-38417 Change 3191437 on 2016/11/09 by Jack.Porter Fix for LandscapeInfo crash when using Force Delete #jira UE-37172 Change 3191033 on 2016/11/08 by Leslie.Nivison Adding licenses for marketplace plugins #jira UEPROD-901 Change 3191028 on 2016/11/08 by Leslie.Nivison Updating licenses due to TPS version updates. Logging undocumented TPS per engine audit #jira UEPROD-900 Change 3190632 on 2016/11/08 by mason.seay Updated testmap and assets #jira UE-29618 Change 3190624 on 2016/11/08 by Jamie.Dale Fixed case where FHTML5TargetPlatform::RefreshHTML5Setup could incorrectly add an empty device Changes to UStrProperty::ExportTextItem caused FParse::Value to (correctly) read an empty string for DevicePath which passed the DirectoryExists check (where it would have previously read "))" which would fail that check). #jira UE-38157 Change 3190443 on 2016/11/08 by Josh.Adams - Somehow checking in my tested shelf messed up #jira UE-38304 Change 3190354 on 2016/11/08 by Josh.Adams - Vulkan now always being compiled in, if the SDK exists. Compiling not dependent on project settings #jira UE-38304 Change 3190123 on 2016/11/08 by zachary.wilson Updating testing content for sureface per-pixel improvements #jira UE-29618 Change 3190113 on 2016/11/08 by Alexis.Matte Make sure the default light map channel is 1 and not 0 #jira UE-35627 Change 3190102 on 2016/11/08 by Dmitry.Rekman Linux: default to binned everywhere (UE-38287). - Fixes suspicious crashes happening in uncooked build. Workaround, needs separate investigation. #jira UE-38287 Change 3190000 on 2016/11/08 by Allan.Bentham Removed old protostar loadmap hack. #jira UE-38342 Change 3189914 on 2016/11/08 by Allan.Bentham Fix vulkan crash when rendering sky capture. Fix crash when rendering LDR scene capture on device. #jira UE-38291 Change 3189861 on 2016/11/08 by Thomas.Sarkanen Fix out of bounds access when using hidden bones with master pose components Code was trying to to access the ReferenceToLocal array using a parent index from the master pose component. Now changed to only use indices known to be valid (i.e. this component's) to index the ReferenceToLocal array. Bone visibility is still master-authoratitive. #jira UE-38214 - [CrashReport] UE4Editor_Engine!UpdateRefToLocalMatrices() [skeletalrender.cpp:238] Change 3189370 on 2016/11/07 by Daniel.Wright Only check transform mismatches for static lighting in UStaticMeshComponent::ApplyComponentInstanceData on components that actually can have static lighting #jira UE-38272 Change 3189358 on 2016/11/07 by Mark.Satterthwaite Intel Metal drivers can no longer compile our compute shaders reliably meaning Intel Macs must always use Metal SM4 as otehrwise they will crash. #jira UE-38299 Change 3189273 on 2016/11/07 by Rolando.Caloca UE4.14 - Integrate fix from 3161219 #jira UE-38270 Change 3189084 on 2016/11/07 by Chris.Bunner Fix RemoveAAJitter from projection matrix. #jira UE-37701, UE-38003 Change 3188636 on 2016/11/07 by Allan.Bentham use glVertexAttribIPointer only on ES3.1 enabled projects. #jira UE-38241 Change 3188596 on 2016/11/07 by Yannick.Lange VR Editor: Fix crash when closing window while in VR Editor #jira UE-37995 Change 3188433 on 2016/11/07 by Matthew.Griffin Add starter content .upack files to starter_content tag so that they should still be installed if templates/feature packs option is de-selected in the Launcher Change 3187739 on 2016/11/04 by Mitchell.Wilson Updating DefautlEditor and DefaultEngine ini to correct path to VehicleMenu level. #jira UE-29748 Change 3187536 on 2016/11/04 by Martin.Wilson Fix for "Renaming a montage section via its details panel doesn't update the section correctly" #jira UE-35929 Change 3187499 on 2016/11/04 by zachary.wilson Checking in content fixes for Lighting Scenarios test level #jira UE-29618 Change 3187492 on 2016/11/04 by mason.seay Updated map to improve testing #jira UE-29618 Change 3187438 on 2016/11/04 by Nick.Shin fix html5 port number for cook-on-the-fly option #jira UE-38032 - Quicklaunch HTML5 fails on Chrome. Browser returns "This site can't be reached 127.0.0.1 refused to connect" Change 3187305 on 2016/11/04 by Martin.Wilson Fix log spam from animation sequence thumbnails #jira UE-38224 Change 3187260 on 2016/11/04 by Lauren.Ridge Fix for crash on opening a level in VR Editing mode. When closing VREditorMode for a level load, HMD no longer leaves stereo mode. #jira UE-32541 Change 3187224 on 2016/11/04 by Robert.Manuszewski Proper fix for a crash when launching BP-only project from the Editor with EDL enabled (does not modify UE4Game target binaries) #jira UE-37617 Change 3187136 on 2016/11/04 by Alexis.Matte Fbx importer for static mesh, make sure that we order the materials array to follow the section order. #jira UE-38242 Change 3187065 on 2016/11/04 by Mitchell.Wilson Updated BP_Commentary_Box to resolve warnings with array if the box opens then closes before the text is rendered. #jira UE-38266 Change 3187056 on 2016/11/04 by Mike.Beach Guarding against a rare crash that occurs when compiling a Blueprint after hot-reload. GUnrealEd was null, which is concerning (as it could have resounding effects in other systems), but as I could not repro it more than once (to figure it out more) I simply guarded the use of a null pointer here. #jira UE-38198 Change 3187040 on 2016/11/04 by Matthew.Griffin Corrected path to DotNETCommon folder Exclude all editor plugin pdbs from stripping #jira UE-37072 Change 3186984 on 2016/11/04 by Marc.Audy Fix crash when null component considered #jira UE-36493 Change 3186600 on 2016/11/04 by Max.Chen Sequencer: Fix crash in sequencer editor mode. #jira UE-38205 Change 3186564 on 2016/11/04 by Nick.Shin checking in latest physx libs for html5 #jira UE-38179 HTML5 Player falls through world on Firefox 64-bit Change 3186258 on 2016/11/03 by Nick.Shin fix for automation build to handle deleting of windows x86 & x64 libs properly #jira UE-38179 HTML5 Player falls through world on Firefox 64-bit Change 3186225 on 2016/11/03 by Lauren.Ridge Fix for foliage brush not showing up until after first motion controller click. #jira UE-38002 Change 3186100 on 2016/11/03 by Chris.Babcock Update local notifications to deal with depreciated API #jira UE-38236 #ue4 #android Change 3186074 on 2016/11/03 by Mitchell.Wilson Rebuilt lighting in Content Examples Welcome level #jira UE-38239 Change 3185923 on 2016/11/03 by Lina.Halper Fixed issue with animation not ticking in inactive world causing it to update parent animation #jira: UE-37933 Change 3185764 on 2016/11/03 by Mitchell.Wilson Updating deprecated node in MyCharacter_UMG. #jira UE-38229 Change 3185683 on 2016/11/03 by Nick.Shin non SSE2 version of PhysX for HTML5 #jira UE-38179 HTML5 Player falls through world on Firefox 64-bit Change 3185492 on 2016/11/03 by Ben.Woodhouse Workaround for very high render query memory overhead on D3D12. Add a cvar to limit timestamp queries allocated by the GPU profiler in a given frame. On D3D12 this limit is 1024 - other RHIs remain unbounded. Currently render queries are 64KB each on D3D12, so this prevents high memory overhead on particular frames, e.g when we render a large number of reflection captures. In practice, most frames are under 400 queries, so in practice we shouldn't hit the limit except in extreme cases. #jira UE-38139 Change 3185481 on 2016/11/03 by Dmitry.Rekman Remove version number from Linux README (UE-38059). #jira UE-38059 Change 3185322 on 2016/11/03 by Ryan.Gerleve Allow path names in NetFieldExportGroups to be remapped on the client. #jira UE-37990 Change 3185293 on 2016/11/03 by Matthew.Griffin Exclude UnrealControls and iPhonePackager from Build Tools CS node on non-Windows platforms as they don't compile #jira UE-34016 Change 3185252 on 2016/11/03 by Michael.Trepka Properly revert to OpenGL on Macs that do not support Metal #jira UE-38190 Change 3184835 on 2016/11/03 by Jurre.deBaare Crash when using undo in the preview scene settings of Persona #fix Ensure that the profile index is valid after undo-ing #misc Added transactions for adding/remove of the profiles #jira UE-38142 Change 3184833 on 2016/11/03 by Jack.Porter Fixed crash when ENABLE_VERIFY_GL and r.MobileOnChipMSAA is enabled on Android #jira UE-38186 Change 3184418 on 2016/11/02 by Ryan.Vance #jira UE-38161 Adding ISceneViewExtension::UsePostInitView which will be used to enable/disable the usage of PostRenderViewFamily_RenderThread and PostRenderView_RenderThread which was added earlier. We need to enable this behavior based on the hmd's compositor behavior, so a simple cvar wont work. I missed the PostPresent implementation for steamvr in the earlier check in. Change 3184286 on 2016/11/02 by Dan.Oconnor Fix for IsValidLowLevel check being rotten. More correct fix will go into Dev-BP, but this is a low risk stop-gap #jira UE-38149 Change 3184283 on 2016/11/02 by Arne.Schober DR - UE-38155 replicated MS CL 3183837 - PSO Dangling Pointers: The PSO cache was returning pointers out of a Map which is based on a sparse Array and those pointers could become invalid if other insertions happen. #jira UE-38155 Change 3184244 on 2016/11/02 by Richard.Ugarte #jira UE-37534 Checking in updated UE4_Demo_Head_D on behalf of MikeB Change 3184171 on 2016/11/02 by Michael.Trepka Made Mac CrashReportClient high-DPI aware and fixed high-DPI handling in FMacWindow::IsPointInWindow() #jira UE-37697 Change 3184126 on 2016/11/02 by Lauren.Ridge VR Editor: Fixes for foliage painting only working on one controller, and for full press not painting foliage. #jira UE-38147 #jira UE-38002 Change 3183997 on 2016/11/02 by Mitchell.Wilson Scaled and Rotated 3d Widget to the correct position on example 2.3 in Content Examples UMG. Adjusted collision on example 1.4 in Content Examples Physics. Updated collision on SM_ExampleMesh_Rocket. Realigned some text render actors in Content Examples Post Process. #jira UE-38099 UE-38078 UE-38064 Change 3183945 on 2016/11/02 by Mieszko.Zielinski Fixed changing AreaClass of NavLinkProxy point links not having any effect on navmesh generation #UE4 #jira UE-38137 Change 3183906 on 2016/11/02 by Nick.Shin for OSX (release-4.14 stream): new OSX clang (from emscripten tool chain) configured by jukka from Mozilla see Engine/Extras/ThirdPartyNotUE/emsdk/emscripten/incoming/EPIC_VERSION for details on where did this version come from fixes for OSX -- update existing (bash shell script and UE4 c#) build files to use the new "incoming" emsdk #jira UE-37329 - Step 'Compile UE4Game HTML5' - 300 Warnings Change 3183899 on 2016/11/02 by Mieszko.Zielinski Fixed EQS debugger not drawing item labels #UE4 #jira UE-38122 Change 3183239 on 2016/11/02 by Peter.Sauerbrei fix for mobile provision with UUID only filename being allowed again by copying them to a new file name which allows them to be used. #jira UE-38006 Change 3183149 on 2016/11/02 by Luke.Thatcher [RELEASE] [SHOOTERGAME] [!] Fix "Is Talking" icon on ShooterGame scoreboard, after PS4 OSS refactor. - ShooterGame was comparing FUniqueNetId::ToString() against AShooterPlayerState::GetShortPlayerName(). - This is wrong, since the NetId is not guaranteed to be equal to the player's name. #jira UE-38011 Change 3183005 on 2016/11/02 by Luke.Thatcher [RELEASE] [PS4] [^] Merging (as edit) PS4 OSS fixes from Engine to OrionGame. #jira UE-38017 UE-38020 Original Changelists: 3182765 [RELEASE] [PS4] [~] Additional logging for PS4 OSS "Play Together". 3182766 [RELEASE] [PS4] [!] Fix assert in FUniqueNetIdPS4::FindOrCreate. We were assuming an online-only ID could never become a local ID. This isn't the case in the following scenario: - Two users join a session on two separate PS4s. - One user signs into the other user's PS4 with the same account, with a second controller. PSN logs him out of the first PS4. - That user's Net ID has now migrated from being online-only, to local-with-online. This is a case that was not handled. 3182767 [RELEASE] [PS4] [!] Fix PS4 session invitations. - Was calling old Web API with SceNpOnlineId where SceNpAccountId is needed. - Replaced with NpToolkit2's session invitation API. 3182892 [RELEASE] [PS4] [!] Fix incorrect identity API implementation in PS4 OSS. - System events directly drive the login state of a user. This also removes the blocking call to sceNpGetState(). - GetAuthToken is only called if the engine calls IOnlineIdentity::Login(). 3182951 [RELEASE] [PS4] [!] Fix "play together" invitations handling in PS4 OSS. - Wrong condition in GetUserWebApiContext. Web API contexts can be created for local users (i.e. FUniqueNetIdPS4 instances with a valid SceUserServiceUserId). Change 3182992 on 2016/11/02 by Nick.Darnell UMG Editor - Fixing a regression with the editor, closing the sequencer tab and reopening the editor should no longer cause a crash. #jira UE-38098 Change 3182951 on 2016/11/02 by Luke.Thatcher [RELEASE] [PS4] [!] Fix "play together" invitations handling in PS4 OSS. - Wrong condition in GetUserWebApiContext. Web API contexts can be created for local users (i.e. FUniqueNetIdPS4 instances with a valid SceUserServiceUserId). #jira UE-38017 [CL3201696by Matthew Griffin in Main branch]
598 lines
20 KiB
Plaintext
598 lines
20 KiB
Plaintext
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
DeferredLightingCommon.usf: Common definitions for deferred lighting.
|
|
=============================================================================*/
|
|
|
|
#ifndef __DEFERRED_LIGHTING_COMMON__
|
|
#define __DEFERRED_LIGHTING_COMMON__
|
|
|
|
#include "DeferredShadingCommon.usf"
|
|
#include "DynamicLightingCommon.usf"
|
|
#include "BRDF.usf"
|
|
#include "MonteCarlo.usf"
|
|
#include "IESLightProfilesCommon.usf"
|
|
#include "ShadingModels.usf"
|
|
|
|
/**
|
|
* Data about a single light.
|
|
* Putting the light data in this struct allows the same lighting code to be used between standard deferred,
|
|
* Where many light properties are known at compile time, and tiled deferred, where all light properties have to be fetched from a buffer.
|
|
*/
|
|
struct FDeferredLightData
|
|
{
|
|
float4 LightPositionAndInvRadius;
|
|
float4 LightColorAndFalloffExponent;
|
|
float3 LightDirection;
|
|
float4 SpotAnglesAndSourceRadius;
|
|
float MinRoughness;
|
|
float ContactShadowLength;
|
|
float2 DistanceFadeMAD;
|
|
float4 ShadowMapChannelMask;
|
|
/** Whether to use inverse squared falloff. */
|
|
bool bInverseSquared;
|
|
/** Whether this is a light with radial attenuation, aka point or spot light. */
|
|
bool bRadialLight;
|
|
/** Whether this light needs spotlight attenuation. */
|
|
bool bSpotLight;
|
|
/** Whether the light should apply shadowing. */
|
|
uint ShadowedBits;
|
|
};
|
|
|
|
/** Data about a single light to be shaded with the simple shading model, designed for speed and limited feature set. */
|
|
struct FSimpleDeferredLightData
|
|
{
|
|
float4 LightPositionAndInvRadius;
|
|
float4 LightColorAndFalloffExponent;
|
|
/** Whether to use inverse squared falloff. */
|
|
bool bInverseSquared;
|
|
};
|
|
|
|
#define REFERENCE_QUALITY 0
|
|
|
|
#undef LIGHT_SOURCE_SHAPE
|
|
#define LIGHT_SOURCE_SHAPE 1
|
|
|
|
#define LIGHT_SHAPE_SPHERE 1
|
|
#define LIGHT_SHAPE_RECT 2
|
|
|
|
static const uint LightSourceShape = LIGHT_SHAPE_SPHERE;
|
|
|
|
bool RayHitRect( float3 R, float3 RectCenter, float3 RectX, float3 RectY, float3 RectZ, float RectExtentX, float RectExtentY )
|
|
{
|
|
// Intersect ray with plane
|
|
float3 PointOnPlane = R * max( 0, dot( RectZ, RectCenter ) / dot( RectZ, R ) );
|
|
|
|
bool InExtentX = abs( dot( RectX, PointOnPlane - RectCenter ) ) <= RectExtentX;
|
|
bool InExtentY = abs( dot( RectY, PointOnPlane - RectCenter ) ) <= RectExtentY;
|
|
return InExtentX && InExtentY;
|
|
}
|
|
|
|
float3 SphereLightingMIS( FGBufferData GBuffer, FDeferredLightData LightData, float3 LobeRoughness, float3 ToLight, float3 V, float3 N, uint2 Random )
|
|
{
|
|
float3 Lighting = 0;
|
|
|
|
LobeRoughness = max( 0.08, LobeRoughness );
|
|
|
|
const float SourceRadius = max( 1, LightData.SpotAnglesAndSourceRadius.z );
|
|
|
|
const float DistanceSqr = dot( ToLight, ToLight );
|
|
const float3 ConeAxis = ToLight * rsqrt( DistanceSqr );
|
|
const float ConeCos = sqrt( 1 - Square( SourceRadius ) / DistanceSqr );
|
|
|
|
const float Area = PI * Square(SourceRadius);
|
|
const float SampleColor = 1.0 / Area;
|
|
|
|
const uint NumSets = 3;
|
|
const uint NumSamples[ NumSets ] =
|
|
{
|
|
0,
|
|
4,
|
|
4,
|
|
};
|
|
|
|
UNROLL
|
|
for( uint Set = 0; Set < NumSets; Set++ )
|
|
{
|
|
LOOP
|
|
for( uint i = 0; i < NumSamples[ Set ]; i++ )
|
|
{
|
|
float2 E = Hammersley( i, NumSamples[ Set ], Random );
|
|
//float2 E = CorrelatedMultiJitter2D( i, NumSamples[ Set ], Random.x * Random.y * (Set + 17) );
|
|
|
|
float3 L, H;
|
|
if( Set == 0 )
|
|
{
|
|
L = TangentToWorld( CosineSampleHemisphere( E ).xyz, N );
|
|
H = normalize(V + L);
|
|
}
|
|
else if( Set == 1 )
|
|
{
|
|
H = TangentToWorld( ImportanceSampleGGX( E, LobeRoughness[1] ).xyz, N );
|
|
L = 2 * dot( V, H ) * H - V;
|
|
}
|
|
else
|
|
{
|
|
L = TangentToWorld( UniformSampleCone( E, ConeCos ).xyz, ConeAxis );
|
|
H = normalize(V + L);
|
|
}
|
|
|
|
float NoL = saturate( dot(N, L) );
|
|
float NoH = saturate( dot(N, H) );
|
|
float VoH = saturate( dot(V, H) );
|
|
|
|
if( NoL > 0 && VoH > 0 )
|
|
{
|
|
BRANCH
|
|
if( Set != 2 && dot( L, ConeAxis ) < ConeCos )
|
|
{
|
|
// Ray misses sphere
|
|
continue;
|
|
}
|
|
|
|
float PDF[] =
|
|
{
|
|
NoL / PI,
|
|
D_GGX( LobeRoughness[1], NoH ) * NoH / (4 * VoH),
|
|
1.0 / ( 2 * PI * (1 - ConeCos) ),
|
|
};
|
|
|
|
// MIS balance heuristic
|
|
float InvWeight = 0;
|
|
UNROLL for( uint j = 0; j < NumSets; j++ )
|
|
{
|
|
InvWeight += PDF[j] * NumSamples[j];
|
|
}
|
|
float Weight = rcp( InvWeight );
|
|
|
|
float3 Shading = SurfaceShading( GBuffer, LobeRoughness, 1, L, V, N, Random ) * NoL;
|
|
Shading += SubsurfaceShading( GBuffer, L, V, N, 1, Random );
|
|
|
|
Lighting += SampleColor * Shading * Weight;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Lighting;
|
|
}
|
|
|
|
// Find representative incoming light direction and energy modification
|
|
float3 AreaLightSpecular( FDeferredLightData LightData, inout float3 LobeRoughness, inout float3 ToLight, inout float3 L, float3 V, half3 N )
|
|
{
|
|
float3 LobeEnergy = 1;
|
|
|
|
LobeRoughness = max( LobeRoughness, LightData.MinRoughness );
|
|
float3 m = LobeRoughness * LobeRoughness;
|
|
|
|
const float SourceRadius = LightData.SpotAnglesAndSourceRadius.z;
|
|
const float SourceLength = LightData.SpotAnglesAndSourceRadius.w;
|
|
|
|
// TODO early out for point lights
|
|
|
|
float3 R = reflect( -V, N );
|
|
float InvDistToLight = rsqrt( dot( ToLight, ToLight ) );
|
|
|
|
// Point lobe in off-specular peak direction
|
|
float a = Square( LobeRoughness[1] );
|
|
R = lerp( N, R, (1 - a) * ( sqrt(1 - a) + a ) );
|
|
R = normalize( R );
|
|
|
|
BRANCH
|
|
if( SourceLength > 0 )
|
|
{
|
|
// Energy conservation
|
|
// asin(x) is angle to sphere, atan(x) is angle to disk, saturate(x) is free and in the middle
|
|
float LineAngle = saturate( SourceLength * InvDistToLight );
|
|
LobeEnergy *= m / saturate( m + 0.5 * LineAngle );
|
|
|
|
// Closest point on line segment to ray
|
|
float3 L01 = LightData.LightDirection * SourceLength;
|
|
float3 L0 = ToLight - 0.5 * L01;
|
|
float3 L1 = ToLight + 0.5 * L01;
|
|
|
|
#if 1
|
|
// Shortest distance
|
|
float a = Square( SourceLength );
|
|
float b = dot( R, L01 );
|
|
float t = saturate( dot( L0, b*R - L01 ) / (a - b*b) );
|
|
#else
|
|
// Smallest angle
|
|
float A = Square( SourceLength );
|
|
float B = 2 * dot( L0, L01 );
|
|
float C = dot( L0, L0 );
|
|
float D = dot( R, L0 );
|
|
float E = dot( R, L01 );
|
|
float t = saturate( (B*D - 2*C*E) / (B*E - 2*A*D) );
|
|
#endif
|
|
|
|
ToLight = L0 + t * L01;
|
|
}
|
|
|
|
BRANCH
|
|
if( SourceRadius > 0 )
|
|
{
|
|
// Energy conservation
|
|
// asin(x) is angle to sphere, atan(x) is angle to disk, saturate(x) is free and in the middle
|
|
float SphereAngle = saturate( SourceRadius * InvDistToLight );
|
|
LobeEnergy *= Square( m / saturate( m + 0.5 * SphereAngle ) );
|
|
|
|
// Closest point on sphere to ray
|
|
float3 ClosestPointOnRay = dot( ToLight, R ) * R;
|
|
float3 CenterToRay = ClosestPointOnRay - ToLight;
|
|
float3 ClosestPointOnSphere = ToLight + CenterToRay * saturate( SourceRadius * rsqrt( dot( CenterToRay, CenterToRay ) ) );
|
|
ToLight = ClosestPointOnSphere;
|
|
}
|
|
|
|
L = normalize( ToLight );
|
|
|
|
return LobeEnergy;
|
|
}
|
|
|
|
/** Returns 0 for positions closer than the fade near distance from the camera, and 1 for positions further than the fade far distance. */
|
|
float DistanceFromCameraFade(float SceneDepth, FDeferredLightData LightData, float3 WorldPosition, float3 CameraPosition)
|
|
{
|
|
// depth (non radial) based fading over distance
|
|
float Fade = saturate(SceneDepth * LightData.DistanceFadeMAD.x + LightData.DistanceFadeMAD.y);
|
|
return Fade * Fade;
|
|
}
|
|
|
|
void GetShadowTerms(FGBufferData GBuffer, FDeferredLightData LightData, float3 WorldPosition, float4 LightAttenuation, out float OpaqueShadowTerm, out float SSSShadowTerm)
|
|
{
|
|
// Remapping the light attenuation buffer (see ShadowRendering.cpp)
|
|
|
|
// LightAttenuation: Light function + per-object shadows in z, per-object SSS shadowing in w,
|
|
// Whole scene directional light shadows in x, whole scene directional light SSS shadows in y
|
|
// Get static shadowing from the appropriate GBuffer channel
|
|
float UsesStaticShadowMap = dot(LightData.ShadowMapChannelMask, float4(1, 1, 1, 1));
|
|
float StaticShadowing = lerp(1, dot(GBuffer.PrecomputedShadowFactors, LightData.ShadowMapChannelMask), UsesStaticShadowMap);
|
|
|
|
if (LightData.bRadialLight)
|
|
{
|
|
// Remapping the light attenuation buffer (see ShadowRendering.cpp)
|
|
|
|
OpaqueShadowTerm = LightAttenuation.z * StaticShadowing;
|
|
// SSS uses a separate shadowing term that allows light to penetrate the surface
|
|
//@todo - how to do static shadowing of SSS correctly?
|
|
SSSShadowTerm = LightAttenuation.w * StaticShadowing;
|
|
}
|
|
else
|
|
{
|
|
// Remapping the light attenuation buffer (see ShadowRendering.cpp)
|
|
// Also fix up the fade between dynamic and static shadows
|
|
// to work with plane splits rather than spheres.
|
|
|
|
float DynamicShadowFraction = DistanceFromCameraFade(GBuffer.Depth, LightData, WorldPosition, View.WorldCameraOrigin);
|
|
// For a directional light, fade between static shadowing and the whole scene dynamic shadowing based on distance + per object shadows
|
|
OpaqueShadowTerm = lerp(LightAttenuation.x, StaticShadowing, DynamicShadowFraction);
|
|
// Fade between SSS dynamic shadowing and static shadowing based on distance
|
|
SSSShadowTerm = min(lerp(LightAttenuation.y, StaticShadowing, DynamicShadowFraction), LightAttenuation.w);
|
|
|
|
// combine with light function
|
|
OpaqueShadowTerm *= LightAttenuation.z;
|
|
SSSShadowTerm *= LightAttenuation.z;
|
|
}
|
|
}
|
|
|
|
float ShadowRayCast(
|
|
float3 RayOriginTranslatedWorld, float3 RayDirection, float ContactShadowLength, float PixelDepthLength,
|
|
int NumSteps, float StepOffset
|
|
)
|
|
{
|
|
const float Epsilon = 0.001;
|
|
float4 RayStartClip = mul( float4( RayOriginTranslatedWorld, 1 ), View.TranslatedWorldToClip );
|
|
float4 RayDirClip = mul( float4( RayDirection * min(PixelDepthLength / length(RayDirection), 1.0 ), 0 ), View.TranslatedWorldToClip );
|
|
float4 RayEndClip = RayStartClip + RayDirClip;
|
|
|
|
float3 RayStartScreen = RayStartClip.xyz / RayStartClip.w;
|
|
float3 RayEndScreen = RayEndClip.xyz / RayEndClip.w;
|
|
|
|
float3 RayStepScreen = RayEndScreen - RayStartScreen;
|
|
float2 AspectRatio = float2(1.0, View.ViewSizeAndInvSize.y * View.ViewSizeAndInvSize.z);
|
|
RayStepScreen *= min(2.0 * ContactShadowLength / length(RayStepScreen.xy * AspectRatio), 1.0);
|
|
|
|
// Clip the ray to the screen borders.
|
|
{
|
|
float2 S = (1.0 + (RayStepScreen.xy < 0 ? 1.0.xx : -1.0.xx) * RayStartScreen.xy) / (abs(RayStepScreen.xy) + Epsilon);
|
|
RayStepScreen *= min(min(S.x, S.y), 1.0);
|
|
}
|
|
|
|
// Avoid self colisions.
|
|
if (RayStepScreen.z < 0.0)
|
|
{
|
|
float2 RayStepPixels = RayStepScreen.xy * 0.5 * View.ViewSizeAndInvSize.xy;
|
|
RayStartScreen.xy += 2.0 * View.ViewSizeAndInvSize.zw * (1.42 * RayStepPixels / length(RayStepPixels));
|
|
}
|
|
RayStartScreen.z += (1.0 - abs(RayDirection.z) / length(RayDirection)) * (0.008 / (PixelDepthLength * ContactShadowLength));
|
|
|
|
float3 RayStartUVz = float3( RayStartScreen.xy * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz, RayStartScreen.z );
|
|
float3 RayStepUVz = float3( RayStepScreen.xy * View.ScreenPositionScaleBias.xy, RayStepScreen.z );
|
|
|
|
float4 RayDepthClip = RayStartClip + mul( float4( 0, 0, PixelDepthLength, 0 ), View.ViewToClip );
|
|
float3 RayDepthScreen = RayDepthClip.xyz / RayDepthClip.w;
|
|
|
|
const float Step = 1.0 / NumSteps;
|
|
|
|
// *2 to get less morie pattern in extreme cases, larger values make object appear not grounded in reflections
|
|
const float CompareTolerance = abs( RayDepthScreen.z - RayStartScreen.z ) * Step * 2;
|
|
|
|
float SampleTime = StepOffset * Step;
|
|
|
|
float FirstHitTime = -1.0;
|
|
|
|
UNROLL
|
|
for( int i = 0; i < NumSteps; i++ )
|
|
{
|
|
float3 SampleUVz = RayStartUVz + RayStepUVz * SampleTime;
|
|
float SampleDepth = SceneDepthTexture.SampleLevel( SceneDepthTextureSampler, SampleUVz.xy, 0 ).r;
|
|
|
|
float DepthDiff = SampleUVz.z - SampleDepth;
|
|
bool Hit = abs( DepthDiff + CompareTolerance ) < CompareTolerance;
|
|
|
|
FirstHitTime = (Hit && FirstHitTime < 0.0) ? SampleTime : FirstHitTime;
|
|
|
|
SampleTime += Step;
|
|
}
|
|
|
|
float Shadow = FirstHitTime > 0.0 ? 1.0 : 0.0;
|
|
|
|
// Off screen masking
|
|
float2 Vignette = max(6.0 * abs(RayStartScreen.xy + RayStepScreen.xy * FirstHitTime) - 5.0, 0.0);
|
|
Shadow *= saturate( 1.0 - dot( Vignette, Vignette ) );
|
|
|
|
return 1 - Shadow;
|
|
}
|
|
|
|
#ifndef SUPPORT_CONTACT_SHADOWS
|
|
#error "Must set SUPPORT_CONTACT_SHADOWS"
|
|
#endif
|
|
|
|
/** Calculates lighting for a given position, normal, etc with a fully featured lighting model designed for quality. */
|
|
float4 GetDynamicLighting(float3 WorldPosition, float3 CameraVector, FGBufferData GBuffer, float AmbientOcclusion, uint ShadingModelID, FDeferredLightData LightData, float4 LightAttenuation, uint2 Random)
|
|
{
|
|
FLightAccumulator LightAccumulator = (FLightAccumulator)0;
|
|
|
|
float3 V = -CameraVector;
|
|
float3 N = GBuffer.WorldNormal;
|
|
float3 L = LightData.LightDirection; // Already normalized
|
|
float3 ToLight = L * GBuffer.Depth;
|
|
float NoL = saturate( dot(N, L) );
|
|
float DistanceAttenuation = 1;
|
|
float LightRadiusMask = 1;
|
|
float SpotFalloff = 1;
|
|
|
|
if (LightData.bRadialLight)
|
|
{
|
|
ToLight = LightData.LightPositionAndInvRadius.xyz - WorldPosition;
|
|
|
|
float DistanceSqr = dot( ToLight, ToLight );
|
|
L = ToLight * rsqrt( DistanceSqr );
|
|
|
|
if (LightData.bInverseSquared)
|
|
{
|
|
const float SourceRadius = LightData.SpotAnglesAndSourceRadius.z;
|
|
const float SourceLength = LightData.SpotAnglesAndSourceRadius.w;
|
|
|
|
BRANCH
|
|
if( SourceLength > 0 )
|
|
{
|
|
// Line segment irradiance
|
|
float3 L01 = LightData.LightDirection * SourceLength;
|
|
float3 ToLight0 = ToLight - 0.5 * L01;
|
|
float3 ToLight1 = ToLight + 0.5 * L01;
|
|
|
|
float LengthSqr0 = dot( ToLight0, ToLight0 );
|
|
float LengthSqr1 = dot( ToLight1, ToLight1 );
|
|
float rLength0 = rsqrt( LengthSqr0 );
|
|
float rLength1 = rsqrt( LengthSqr1 );
|
|
float Length0 = LengthSqr0 * rLength0;
|
|
float Length1 = LengthSqr1 * rLength1;
|
|
|
|
DistanceAttenuation = rcp( ( Length0 * Length1 + dot( ToLight0, ToLight1 ) ) * 0.5 + 1 );
|
|
NoL = saturate( 0.5 * ( dot(N, ToLight0) * rLength0 + dot(N, ToLight1) * rLength1 ) );
|
|
}
|
|
else
|
|
{
|
|
DistanceAttenuation = rcp( DistanceSqr + 1 );
|
|
NoL = saturate( dot( N, L ) );
|
|
|
|
if( SourceRadius > 0 )
|
|
{
|
|
#if 1 //HORIZON
|
|
NoL = dot( N, L );
|
|
|
|
float SinAlphaSqr = saturate( Square( SourceRadius ) / DistanceSqr );
|
|
float SinAlpha = sqrt( SinAlphaSqr );
|
|
|
|
if( NoL < SinAlpha )
|
|
{
|
|
#if 0
|
|
// Accurate sphere irradiance
|
|
float CosBeta = NoL;
|
|
float SinBeta = sqrt( 1 - CosBeta * CosBeta );
|
|
float TanBeta = SinBeta / CosBeta;
|
|
|
|
float x = sqrt( 1 / SinAlphaSqr - 1 );
|
|
float y = -x / TanBeta;
|
|
float z = SinBeta * sqrt(1 - y*y);
|
|
|
|
DistanceAttenuation = SinAlphaSqr * ( NoL * acos(y) - x * z ) + atan( z / x );
|
|
DistanceAttenuation /= PI * Square( SourceRadius );
|
|
NoL = 1;
|
|
#else
|
|
// Hermite spline approximation
|
|
// Fairly accurate with SinAlpha < 0.8
|
|
// y=0 and dy/dx=0 at -SinAlpha
|
|
// y=SinAlpha and dy/dx=1 at SinAlpha
|
|
NoL = max( NoL, -SinAlpha );
|
|
NoL = Square( SinAlpha + NoL ) / ( 4 * SinAlpha );
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// TODO optimize
|
|
LightRadiusMask = Square( saturate( 1 - Square( DistanceSqr * Square(LightData.LightPositionAndInvRadius.w) ) ) );
|
|
}
|
|
else
|
|
{
|
|
DistanceAttenuation = 1;
|
|
NoL = saturate( dot( N, L ) );
|
|
|
|
LightRadiusMask = RadialAttenuation(ToLight * LightData.LightPositionAndInvRadius.w, LightData.LightColorAndFalloffExponent.w);
|
|
|
|
#if REFERENCE_QUALITY
|
|
// anti Area
|
|
LightRadiusMask *= DistanceSqr + 1;
|
|
#endif
|
|
}
|
|
|
|
if (LightData.bSpotLight)
|
|
{
|
|
SpotFalloff = SpotAttenuation(L, -LightData.LightDirection, LightData.SpotAnglesAndSourceRadius.xy);
|
|
}
|
|
}
|
|
|
|
LightAccumulator.EstimatedCost += 0.3f; // running the PixelShader at all has a cost
|
|
|
|
BRANCH
|
|
if (LightRadiusMask > 0 && SpotFalloff > 0)
|
|
{
|
|
float SurfaceShadow = 1;
|
|
float SubsurfaceShadow = 1;
|
|
|
|
BRANCH
|
|
if (LightData.ShadowedBits)
|
|
{
|
|
GetShadowTerms(GBuffer, LightData, WorldPosition, LightAttenuation, SurfaceShadow, SubsurfaceShadow);
|
|
|
|
// greatly reduces shadow mapping artifacts
|
|
// Commented out because it reduces character shading quality.
|
|
//SurfaceShadow *= saturate(dot(N, L) * 6 - 0.2);
|
|
|
|
#if SUPPORT_CONTACT_SHADOWS
|
|
BRANCH
|
|
if( LightData.ShadowedBits > 1 && LightData.ContactShadowLength > 0 )
|
|
{
|
|
float StepOffset = float( Random.x & 0xffff ) / (1<<16) + 0.1;
|
|
|
|
float Shadow = ShadowRayCast( WorldPosition + View.PreViewTranslation, ToLight, LightData.ContactShadowLength, GBuffer.Depth, 8, StepOffset );
|
|
|
|
SurfaceShadow *= Shadow;
|
|
//SubsurfaceShadow *= Shadow;
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
SurfaceShadow = AmbientOcclusion;
|
|
}
|
|
|
|
#if SUPPORT_CONTACT_SHADOWS
|
|
BRANCH
|
|
if( LightData.ShadowedBits < 2 && GBuffer.ShadingModelID == SHADINGMODELID_HAIR )
|
|
{
|
|
float StepOffset = float( Random.x & 0xffff ) / (1<<16) + 0.1;
|
|
|
|
SubsurfaceShadow = ShadowRayCast( WorldPosition + View.PreViewTranslation, L, 0.1, GBuffer.Depth, 8, StepOffset );
|
|
}
|
|
#endif
|
|
|
|
float SurfaceAttenuation = (DistanceAttenuation * LightRadiusMask * SpotFalloff) * SurfaceShadow;
|
|
float SubsurfaceAttenuation = (DistanceAttenuation * LightRadiusMask * SpotFalloff) * SubsurfaceShadow;
|
|
|
|
LightAccumulator.EstimatedCost += 0.3f; // add the cost of getting the shadow terms
|
|
|
|
const bool bNeedsSeparateSubsurfaceLightAccumulation = GBuffer.ShadingModelID == SHADINGMODELID_SUBSURFACE_PROFILE;
|
|
const float3 LightColor = LightData.LightColorAndFalloffExponent.rgb;
|
|
|
|
#if NON_DIRECTIONAL_DIRECT_LIGHTING
|
|
|
|
float3 VolumeLighting = Diffuse_Lambert(GBuffer.DiffuseColor);
|
|
LightAccumulator_Add(LightAccumulator, VolumeLighting, (1.0/PI), LightColor * SurfaceAttenuation, bNeedsSeparateSubsurfaceLightAccumulation);
|
|
|
|
#else
|
|
{
|
|
const float ClearCoatRoughness = GBuffer.CustomData.y;
|
|
|
|
float3 LobeRoughness = float3(ClearCoatRoughness, GBuffer.Roughness, 1);
|
|
|
|
#if REFERENCE_QUALITY
|
|
float LightMask = LightRadiusMask * SpotFalloff * SurfaceShadow;
|
|
LightAccumulator_Add(LightAccumulator, SphereLightingMIS( GBuffer, LightData, LobeRoughness, ToLight, V, N, Random ), 0, LightColor * LightMask, bNeedsSeparateSubsurfaceLightAccumulation);
|
|
#else
|
|
float3 LobeEnergy = AreaLightSpecular(LightData, LobeRoughness, ToLight, L, V, N);
|
|
|
|
// accumulate surface
|
|
{
|
|
float3 SurfaceLighting = SurfaceShading(GBuffer, LobeRoughness, LobeEnergy, L, V, N, Random);
|
|
LightAccumulator_Add(LightAccumulator, SurfaceLighting, (1.0/PI), LightColor * (NoL * SurfaceAttenuation), bNeedsSeparateSubsurfaceLightAccumulation);
|
|
}
|
|
|
|
// accumulate subsurface
|
|
{
|
|
float3 SubsurfaceLighting = SubsurfaceShading(GBuffer, L, V, N, SubsurfaceShadow, Random);
|
|
|
|
LightAccumulator_Add(LightAccumulator, SubsurfaceLighting, 0, LightColor * SubsurfaceAttenuation, false);
|
|
|
|
LightAccumulator.EstimatedCost += 0.4f; // add the cost of the lighting computations (should sum up to 1 form one light)
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return LightAccumulator_GetResult(LightAccumulator);
|
|
}
|
|
|
|
/**
|
|
* Calculates lighting for a given position, normal, etc with a simple lighting model designed for speed.
|
|
* All lights rendered through this method are unshadowed point lights with no shadowing or light function or IES.
|
|
* A cheap specular is used instead of the more correct area specular, no fresnel.
|
|
*/
|
|
float3 GetSimpleDynamicLighting(float3 WorldPosition, float3 CameraVector, float3 WorldNormal, float AmbientOcclusion, float3 DiffuseColor, float3 SpecularColor, float Roughness, FSimpleDeferredLightData LightData)
|
|
{
|
|
float3 V = -CameraVector;
|
|
float3 N = WorldNormal;
|
|
float3 ToLight = LightData.LightPositionAndInvRadius.xyz - WorldPosition;
|
|
float DistanceAttenuation = 1;
|
|
|
|
float DistanceSqr = dot( ToLight, ToLight );
|
|
float3 L = ToLight * rsqrt( DistanceSqr );
|
|
float NoL = saturate( dot( N, L ) );
|
|
|
|
if (LightData.bInverseSquared)
|
|
{
|
|
// Sphere falloff (technically just 1/d2 but this avoids inf)
|
|
DistanceAttenuation = 1 / ( DistanceSqr + 1 );
|
|
|
|
float LightRadiusMask = Square( saturate( 1 - Square( DistanceSqr * Square(LightData.LightPositionAndInvRadius.w) ) ) );
|
|
DistanceAttenuation *= LightRadiusMask;
|
|
}
|
|
else
|
|
{
|
|
DistanceAttenuation = RadialAttenuation(ToLight * LightData.LightPositionAndInvRadius.w, LightData.LightColorAndFalloffExponent.w);
|
|
}
|
|
|
|
float3 OutLighting = 0;
|
|
|
|
BRANCH
|
|
if (DistanceAttenuation > 0)
|
|
{
|
|
const float3 LightColor = LightData.LightColorAndFalloffExponent.rgb;
|
|
|
|
// Apply SSAO to the direct lighting since we're not going to have any other shadowing
|
|
float Attenuation = DistanceAttenuation * AmbientOcclusion;
|
|
|
|
#if NON_DIRECTIONAL_DIRECT_LIGHTING
|
|
float3 VolumeLighting = Diffuse_Lambert(DiffuseColor);
|
|
OutLighting += LightColor * Attenuation * VolumeLighting;
|
|
#else
|
|
OutLighting += LightColor * (NoL * Attenuation) * SimpleShading(DiffuseColor, SpecularColor, max(Roughness, .04f), L, V, N);
|
|
#endif
|
|
}
|
|
|
|
return OutLighting;
|
|
}
|
|
|
|
#endif |