/************************************************************************************ Depthkit Unity SDK License v1 Copyright 2016-2024 Simile Inc dba Scatter. All Rights reserved. Licensed under the the Simile Inc dba Scatter ("Scatter") Software Development Kit License Agreement (the "License"); you may not use this SDK except in compliance with the License, which is provided at the time of installation or download, or which otherwise accompanies this software in either electronic or hard copy form. You may obtain a copy of the License at http://www.depthkit.tv/license-agreement-v1 Unless required by applicable law or agreed to in writing, the SDK distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ************************************************************************************/ #ifndef _DEPTHKIT_STUDIO_CGINC #define _DEPTHKIT_STUDIO_CGINC #include "Packages/nyc.scatter.depthkit.core/Runtime/Resources/Shaders/Includes/Depthkit.cginc" #include "Packages/nyc.scatter.depthkit.core/Runtime/Resources/Shaders/Includes/SampleEdgeMask.cginc" #include "Packages/nyc.scatter.depthkit.studio/Runtime/Resources/Shaders/Includes/DepthkitStudioUniforms.cginc" DK_EDGEMASK_UNIFORMS float viewBlend(float cosTheta, float multiplier) { float scale = 1.0 / max(multiplier, FLOAT_EPS); return 1.0 / (1.0 + scale + cosTheta * -1.0) * scale; } #ifdef DK_UNTEXTURED_FRAGMENT_INFER float4 GetCamContribution(uint perspectiveIndex, float3 surfaceToEyeDir, float3 pos3d, float3 normal, inout float4 fallbackColor1, inout float4 fallbackColor2) #else float4 GetCamContribution(uint perspectiveIndex, float3 surfaceToEyeDir, float3 pos3d, float3 normal) #endif { //ignore cameras from backfacing directions float3 sensorPosition = dkGetDepthCameraPosition(perspectiveIndex); float3 surfaceToSensorDir = normalize(sensorPosition - pos3d); float normalDotSensor = dot(surfaceToSensorDir, normal); float normWeight = step(0.0f, normalDotSensor); // back-project into NDC camera space then into texture space for sampling depth and colour frames float2 perspectiveUV, colorUV, depthUV; float3 depthViewSpacePos; dkWorldToPerspectiveUV(perspectiveIndex, pos3d, perspectiveUV, depthUV, colorUV, depthViewSpacePos); float2 inBounds = step(float2(0.0f, 0.0f), perspectiveUV.xy) * step(perspectiveUV.xy, float2(1.0f, 1.0f)); float valid = inBounds.x * inBounds.y * (float)(_PerspectiveColorBlending[perspectiveIndex].enablePerspective); // calculate weights float viewWeight = viewBlend(dot(surfaceToEyeDir, surfaceToSensorDir), _GlobalViewDependentColorBlendWeight * 5.0); // normal based weighting normWeight *= pow(max(normalDotSensor, 0), _SurfaceNormalColorBlendingPower); float mixedWeight = valid * viewWeight * normWeight; #ifndef DK_UNTEXTURED_FRAGMENT_INFER // early out before any texture sampling if possible if (mixedWeight <= 0) return float4(0, 0, 0, 0); #endif #if defined(DK_USE_EDGEMASK) float2 maskUV = perspectiveUV.xy * _PaddedUVScaleFactor; float edgeMaskValue = _MaskTexture.SampleLevel(_Mask_LinearClamp, float3(maskUV, _PerspectiveToSlice[perspectiveIndex].x), 0).r; float edgeWeight = 10.0f / (10.0f + pow(edgeMaskValue * (1 + viewWeight), 5.0f)); mixedWeight *= edgeWeight; #endif //sample depth and color w/ bilinear interpolation float depth = dkSampleDepth(depthUV, perspectiveIndex, perspectiveUV); valid *= (float)dkValidateNormalizedDepth(perspectiveIndex, depth); mixedWeight *= valid; float3 unprojected = dkPerspectiveUVToWorld(perspectiveIndex, perspectiveUV, depth).xyz; float disparity = distance(unprojected, pos3d); //interpolate over the disparity threshold mixedWeight *= smoothstep(_PerViewDisparityThreshold + _PerViewDisparityBlendWidth, _PerViewDisparityThreshold - _PerViewDisparityBlendWidth, disparity); #if defined(DK_USE_DEBUG_COLOR) float3 newColor = dkGetDebugCameraColor(perspectiveIndex); #elif defined(DK_USE_EDGEMASK) && defined(DK_DEBUG_EDGEMASK) float3 newColor = dkGetDebugCameraColor(perspectiveIndex); mixedWeight = edgeWeight * valid; #else float3 newColor = dkSampleColor(colorUV); #endif #ifdef DK_UNTEXTURED_FRAGMENT_INFER // Last level fallback is view dependence and validity only float fallbackWeight = valid * viewWeight; fallbackColor2 += float4(newColor * fallbackWeight, fallbackWeight); // First level fallback also includes normal weight to prevent texture from cameras that can't see the surface at all fallbackWeight *= normWeight; fallbackColor1 += float4(newColor * fallbackWeight, fallbackWeight); #endif return float4(newColor * mixedWeight, mixedWeight); } float3 dkSampleColorViewWeightedReprojection(float3 surfaceToEyeDir, float3 objectPosition, float3 objectNormal) { float4 accumulatedColor = float4(0, 0, 0, 0); #ifdef DK_UNTEXTURED_FRAGMENT_INFER float4 fallbackColor1 = float4(0, 0, 0, 0); float4 fallbackColor2 = float4(0, 0, 0, 0); #endif for (uint perspectiveIndex = 0; perspectiveIndex < (uint) _PerspectivesCount; perspectiveIndex++) { #ifdef DK_UNTEXTURED_FRAGMENT_INFER accumulatedColor += GetCamContribution(perspectiveIndex, surfaceToEyeDir, objectPosition, objectNormal, fallbackColor1, fallbackColor2); #else accumulatedColor += GetCamContribution(perspectiveIndex, surfaceToEyeDir, objectPosition, objectNormal); #endif } if (accumulatedColor.w > 0.0f) { accumulatedColor.rgb /= accumulatedColor.w; } #ifdef DK_UNTEXTURED_FRAGMENT_INFER else if (fallbackColor1.w > 0.0f) { accumulatedColor.rgb = fallbackColor1.rgb / fallbackColor1.w; } else if (fallbackColor2.w > 0.0f) { accumulatedColor.rgb = fallbackColor2.rgb / fallbackColor2.w; } #endif else { #ifdef DK_UNTEXTURED_FRAGMENT_CLIP discard; #endif #ifdef DK_UNTEXTURED_FRAGMENT_COLORIZE accumulatedColor.rgb = _UntexturedFragDefaultColor; #endif } return accumulatedColor.rgb; } #endif // _DEPTHKIT_STUDIO_CGINC