#define THREADGROUP_DIMENSION_X 8 #define THREADGROUP_DIMENSION_Y 8 #pragma kernel ThreeTapCheckerboardVR #pragma kernel FourTapCornersVR #pragma kernel FourTapCrossVR #pragma kernel FiveTapStarVR #pragma kernel SevenTapHexagonalVR #pragma kernel EightTapCornersAndCrossVR #pragma kernel NineTapOctagonalVR #pragma kernel QuadraticHorizontalVR #pragma kernel QuadraticVerticalVR #pragma kernel GaussianHorizontalVR #pragma kernel GaussianVerticalVR Texture2DArray Source; RWTexture2DArray Result; float2 ResultDimensions; float SampleDist; float SampleOffset; bool OffsetCenter; uint BlurIteration; uint TapsPerSideHor; uint TapsPerSideVert; SamplerState linearClampSampler; [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void ThreeTapCheckerboardVR(uint3 id : SV_DispatchThreadID) { const float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const float2 texelIndex = floor(idf); const half checker = 1 - 2 * fmod(floor(0.5h * BlurIteration) + texelIndex.x + texelIndex.y, 2); const half orientation = fmod(BlurIteration, 2); const half invOrientation = 1.0h - orientation; const half texelWidth = 1.0h / ResultDimensions.x; const half texelHeight = 1.0h / ResultDimensions.y; const half horOffset = texelWidth * SampleDist; const half vertOffset = texelHeight * SampleDist; const half2 offset1 = half2( checker * (0.5h * texelWidth * invOrientation + horOffset * orientation), checker * (vertOffset * invOrientation + 0.5h * texelHeight * orientation) ); const half2 offset2 = half2( lerp(horOffset, -horOffset * checker, orientation), lerp(-vertOffset * checker, vertOffset, orientation) ); const half2 offset3 = half2( lerp(-horOffset, -horOffset * checker, orientation), lerp(-vertOffset * checker, -vertOffset, orientation) ); const half4 sumL = 0.334h * Source.SampleLevel(linearClampSampler, uv + half3(offset1, 0), 0) + 0.333h * Source.SampleLevel(linearClampSampler, uv + half3(offset2, 0), 0) + 0.333h * Source.SampleLevel(linearClampSampler, uv + half3(offset3, 0), 0); Result[half3(id.xy, 0)] = sumL; uv.z = 1; const half4 sumR = 0.334h * Source.SampleLevel(linearClampSampler, uv + half3(offset1, 0), 0) + 0.333h * Source.SampleLevel(linearClampSampler, uv + half3(offset2, 0), 0) + 0.333h * Source.SampleLevel(linearClampSampler, uv + half3(offset3, 0), 0); Result[half3(id.xy, 1)] = sumR; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void FourTapCornersVR(uint3 id : SV_DispatchThreadID) { const float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half2 sampleDist = SampleDist / ResultDimensions; const half4 sumL = 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, sampleDist.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, sampleDist.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, -sampleDist.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, -sampleDist.y, 0), 0); Result[half3(id.xy, 0)] = sumL; uv.z = 1; const half4 sumR = 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, sampleDist.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, sampleDist.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, -sampleDist.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, -sampleDist.y, 0), 0); Result[half3(id.xy, 1)] = sumR; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void FourTapCrossVR(uint3 id : SV_DispatchThreadID) { const float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half2 sampleDist = SampleDist / ResultDimensions; const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y); const half2 halfTexelOffset = texelSize * SampleOffset; const half4 sumL = 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, halfTexelOffset.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, halfTexelOffset.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, sampleDist.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, -sampleDist.y, 0), 0); Result[half3(id.xy, 0)] = sumL; uv.z = 1; const half4 sumR = 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, halfTexelOffset.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, halfTexelOffset.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, sampleDist.y, 0), 0) + 0.25h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, -sampleDist.y, 0), 0); Result[half3(id.xy, 1)] = sumR; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void FiveTapStarVR(uint3 id : SV_DispatchThreadID) { const float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half2 offset = SampleDist / ResultDimensions; const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y); const half2 halfTexelOffset = texelSize * SampleOffset; const half4 sumL = 0.5h * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0) + 0.125h * Source.SampleLevel(linearClampSampler, uv + half3( offset.x, offset.y, 0), 0) + 0.125h * Source.SampleLevel(linearClampSampler, uv + half3(-offset.x, offset.y, 0), 0) + 0.125h * Source.SampleLevel(linearClampSampler, uv + half3( offset.x, -offset.y, 0), 0) + 0.125h * Source.SampleLevel(linearClampSampler, uv + half3(-offset.x, -offset.y, 0), 0); Result[half3(id.xy, 0)] = sumL; uv.z = 1; const half4 sumR = 0.5h * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0) + 0.125h * Source.SampleLevel(linearClampSampler, uv + half3( offset.x, offset.y, 0), 0) + 0.125h * Source.SampleLevel(linearClampSampler, uv + half3(-offset.x, offset.y, 0), 0) + 0.125h * Source.SampleLevel(linearClampSampler, uv + half3( offset.x, -offset.y, 0), 0) + 0.125h * Source.SampleLevel(linearClampSampler, uv + half3(-offset.x, -offset.y, 0), 0); Result[half3(id.xy, 1)] = sumR; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void SevenTapHexagonalVR(uint3 id : SV_DispatchThreadID) { const float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half sampleDistanceX = SampleDist / ResultDimensions.x * 0.57735024648h; const half sampleDistanceY = SampleDist / ResultDimensions.y; const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y); const half2 halfTexelOffset = texelSize * SampleOffset; const half4 sumL = 0.28h * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX * 2, halfTexelOffset.y, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX * 2, halfTexelOffset.y, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX, sampleDistanceY, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX, -sampleDistanceY, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX, sampleDistanceY, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX, -sampleDistanceY, 0), 0); Result[half3(id.xy, 0)] = sumL; uv.z = 1; const half4 sumR = 0.28h * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX * 2, halfTexelOffset.y, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX * 2, halfTexelOffset.y, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX, sampleDistanceY, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX, -sampleDistanceY, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX, sampleDistanceY, 0), 0) + 0.12h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX, -sampleDistanceY, 0), 0); Result[half3(id.xy, 1)] = sumR; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void EightTapCornersAndCrossVR(uint3 id : SV_DispatchThreadID) { const float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half2 sampleDist = SampleDist / ResultDimensions; const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y); const half2 halfTexelOffset = texelSize * SampleOffset; const half4 sumL = 0.165h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, sampleDist.y, 0), 0) + 0.165h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, sampleDist.y, 0), 0) + 0.165h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, -sampleDist.y, 0), 0) + 0.165h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, -sampleDist.y, 0), 0) + 0.085h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, sampleDist.y * 2, 0), 0) + 0.085h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, -sampleDist.y * 2, 0), 0) + 0.085h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x * 2, halfTexelOffset.y, 0), 0) + 0.085h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x * 2, halfTexelOffset.y, 0), 0); Result[half3(id.xy, 0)] = sumL; uv.z = 1; const half4 sumR = 0.165h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, sampleDist.y, 0), 0) + 0.165h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, sampleDist.y, 0), 0) + 0.165h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, -sampleDist.y, 0), 0) + 0.165h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, -sampleDist.y, 0), 0) + 0.085h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, sampleDist.y * 2, 0), 0) + 0.085h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, -sampleDist.y * 2, 0), 0) + 0.085h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x * 2, halfTexelOffset.y, 0), 0) + 0.085h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x * 2, halfTexelOffset.y, 0), 0); Result[half3(id.xy, 1)] = sumR; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void NineTapOctagonalVR(uint3 id : SV_DispatchThreadID) { const float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half2 sampleDist = SampleDist / ResultDimensions; const half2 sampleDist2 = sampleDist * 1.414427h; const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y); const half2 halfTexelOffset = texelSize * SampleOffset; const half4 sumL = 0.2h * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist2.x, halfTexelOffset.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist2.x, halfTexelOffset.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, sampleDist2.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, -sampleDist2.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, sampleDist.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, sampleDist.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, -sampleDist.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, -sampleDist.y, 0), 0); Result[half3(id.xy, 0)] = sumL; uv.z = 1; const half4 sumR = 0.2h * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist2.x, halfTexelOffset.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist2.x, halfTexelOffset.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, sampleDist2.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( halfTexelOffset.x, -sampleDist2.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, sampleDist.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, sampleDist.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3( sampleDist.x, -sampleDist.y, 0), 0) + 0.1h * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDist.x, -sampleDist.y, 0), 0); Result[half3(id.xy, 1)] = sumR; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void QuadraticHorizontalVR(uint3 id : SV_DispatchThreadID) { float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half sampleDistanceX = SampleDist / ResultDimensions.x; const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y); const half2 halfTexelOffset = texelSize * SampleOffset; half4 colorL = Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0); half totalWeight = 1.h; for (uint slotL = 1; slotL <= TapsPerSideHor; slotL++) { const half t = 1 - slotL / (TapsPerSideHor + 1.); const half weight = t * t; colorL += weight * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX * slotL, halfTexelOffset.y, 0), 0); colorL += weight * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX * slotL, halfTexelOffset.y, 0), 0); totalWeight += 2 * weight; } Result[half3(id.xy, 0)] = colorL / totalWeight; uv.z = 1; half4 ColorR = Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0); totalWeight = 1.h; for (uint slotR = 1; slotR <= TapsPerSideHor; slotR++) { const half t = 1 - slotR / (TapsPerSideHor + 1.); const half weight = t * t; ColorR += weight * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX * slotR, halfTexelOffset.y, 0), 0); ColorR += weight * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX * slotR, halfTexelOffset.y, 0), 0); totalWeight += 2 * weight; } Result[half3(id.xy, 1)] = ColorR / totalWeight; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void QuadraticVerticalVR(uint3 id : SV_DispatchThreadID) { float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half sampleDistanceY = SampleDist / ResultDimensions.y; const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y); const half2 halfTexelOffset = texelSize * SampleOffset; half4 colorL = Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0); half totalWeight = 1.h; for (uint slotL = 1; slotL <= TapsPerSideVert; slotL++) { const half t = 1 - slotL / (TapsPerSideVert + 1.); const half weight = t * t; colorL += weight * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset.x, sampleDistanceY * slotL, 0), 0); colorL += weight * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset.x, -sampleDistanceY * slotL, 0), 0); totalWeight += 2 * weight; } Result[half3(id.xy, 0)] = colorL / totalWeight; uv.z = 1; half4 colorR = Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0); totalWeight = 1.h; for (uint slotR = 1; slotR <= TapsPerSideVert; slotR++) { const half t = 1 - slotR / (TapsPerSideVert + 1.); const half weight = t * t; colorR += weight * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset.x, sampleDistanceY * slotR, 0), 0); colorR += weight * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset.x, -sampleDistanceY * slotR, 0), 0); totalWeight += 2 * weight; } Result[half3(id.xy, 1)] = colorR / totalWeight; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void GaussianHorizontalVR(uint3 id : SV_DispatchThreadID) { float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half lowTapAdjust = 0.8h * max(0, 6 - TapsPerSideHor * 0.2h); const half sigma = (lowTapAdjust + TapsPerSideHor) * 2 / 6.; const half weightExpDivisor = -2 * sigma * sigma; const half sampleDistanceX = SampleDist / ResultDimensions.x; const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y); const half2 halfTexelOffset = texelSize * SampleOffset; half4 colorL = Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0); half totalWeight = 1.h; for (uint slotL = 1; slotL <= TapsPerSideHor; slotL++) { const half weight = exp(slotL * slotL / weightExpDivisor); colorL += weight * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX * slotL, halfTexelOffset.y, 0), 0); colorL += weight * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX * slotL, halfTexelOffset.y, 0), 0); totalWeight += 2 * weight; } Result[half3(id.xy, 0)] = colorL / totalWeight; uv.z = 1; half4 colorR = Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0); totalWeight = 1.h; for (uint slotR = 1; slotR <= TapsPerSideHor; slotR++) { const half weight = exp(slotR * slotR / weightExpDivisor); colorR += weight * Source.SampleLevel(linearClampSampler, uv + half3( sampleDistanceX * slotR, halfTexelOffset.y, 0), 0); colorR += weight * Source.SampleLevel(linearClampSampler, uv + half3(-sampleDistanceX * slotR, halfTexelOffset.y, 0), 0); totalWeight += 2 * weight; } Result[half3(id.xy, 1)] = colorR / totalWeight; } [numthreads(THREADGROUP_DIMENSION_X, THREADGROUP_DIMENSION_Y, 1)] void GaussianVerticalVR(uint3 id : SV_DispatchThreadID) { float2 idf = id.xy + 0.5h; half3 uv = half3(idf / ResultDimensions, 0); const half lowTapAdjust = 0.8h * max(0, 6 - TapsPerSideVert * 0.2h); const half sigma = (lowTapAdjust + TapsPerSideVert) * 2 / 6.; const half weightExpDivisor = -2 * sigma * sigma; const half sampleDistanceY = SampleDist / ResultDimensions.y; const half2 texelSize = half2(1.h / ResultDimensions.x, 1.h / ResultDimensions.y); const half2 halfTexelOffset = texelSize * SampleOffset; half4 colorL = Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0); half totalWeight = 1.h; for (uint slotL = 1; slotL <= TapsPerSideVert; slotL++) { const half weight = exp(slotL * slotL / weightExpDivisor); colorL += weight * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset.x, sampleDistanceY * slotL, 0), 0); colorL += weight * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset.x, -sampleDistanceY * slotL, 0), 0); totalWeight += 2 * weight; } Result[half3(id.xy, 0)] = colorL / totalWeight; uv.z = 1; half4 colorR = Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset * OffsetCenter, 0), 0); totalWeight = 1.h; for (uint slotR = 1; slotR <= TapsPerSideVert; slotR++) { const half weight = exp(slotR * slotR / weightExpDivisor); colorR += weight * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset.x, sampleDistanceY * slotR, 0), 0); colorR += weight * Source.SampleLevel(linearClampSampler, uv + half3(halfTexelOffset.x, -sampleDistanceY * slotR, 0), 0); totalWeight += 2 * weight; } Result[half3(id.xy, 1)] = colorR / totalWeight; }