#pragma kernel TileMerge MERGE_PASS SCATTERING #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/MotionBlurTileCommon.hlsl" TEXTURE2D_X_UINT(_TileToScatterMax); TEXTURE2D_X(_TileToScatterMin); RW_TEXTURE2D_X(float3, _TileMaxNeighbourhood); [numthreads(8, 8, 1)] void TileMerge(uint3 dispatchID : SV_DispatchThreadID) { UNITY_XR_ASSIGN_VIEW_INDEX(dispatchID.z); int2 id = dispatchID.xy; // If we scattered wider than a 3 tile radius, then we do an additional neighbourhood search. float2 maxVelData = UnpackMotionVec(_TileToScatterMax[COORD_TEXTURE2D_X(id)]); float maxVelLen = MotionVecLengthInPixelsFromEncoded(maxVelData); // TODO: In theory this could have to be even wider. In general, we need a better way to determine min velocities. float minVel = 0.0f; int2 maxCoords = int2(_TileTargetSize.xy - 1); if (maxVelLen > TILE_SIZE*0.5f) { int tileCount = maxVelLen / TILE_SIZE; if (tileCount > 4) tileCount = 4; minVel = 999999.0f; // This is sub-optimal, but the texture is tiny and should be fairly cache efficient. for (int x = -tileCount; x < tileCount; ++x) { for (int y = -tileCount; y < tileCount; ++y) { int2 tapCoord = clamp(id + int2(x, y), 0, _TileTargetSize.xy - 1); float data = _TileToScatterMin[COORD_TEXTURE2D_X(tapCoord)].x; minVel = min(minVel, data); } } } else { minVel = _TileToScatterMin[COORD_TEXTURE2D_X(id)].x; } _TileMaxNeighbourhood[COORD_TEXTURE2D_X(id)] = float3(UnpackMotionVec(_TileToScatterMax[COORD_TEXTURE2D_X(id)]), (minVel)); }