#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl" #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/PostProcessDefines.hlsl" #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch #pragma kernel KMain #pragma multi_compile GENERIC UNITDISTANCE #pragma multi_compile _ ENABLE_ALPHA TEXTURE2D_X(_InputTexture); RW_TEXTURE2D_X(CTYPE, _OutputTexture); SAMPLER(sampler_LinearClamp); CBUFFER_START(cb0) float4 _Params; CBUFFER_END #define GROUP_SIZE 8 // Back-ported & adapted from the work of the Stockholm demo team - thanks Lasse float2 Panini_UnitDistance(float2 view_pos) { // Given // S----------- E--X------- // | ` . /,´ // |-- --- Q // 1 | ,´/ ` // | ,´ / ´ // | ,´ / ` // | ,´ / . // O` / . // | / ` // | / ´ // 1 | / ´ // | / ´ // |/_ . ´ // P // // Have E // Want to find X // // First apply tangent-secant theorem to find Q // PE*QE = SE*SE // QE = PE-PQ // PQ = PE-(SE*SE)/PE // Q = E*(PQ/PE) // Then project Q to find X const float d = 1.0; const float view_dist = 2.0; const float view_dist_sq = 4.0; float view_hyp = sqrt(view_pos.x * view_pos.x + view_dist_sq); float cyl_hyp = view_hyp - (view_pos.x * view_pos.x) / view_hyp; float cyl_hyp_frac = cyl_hyp / view_hyp; float cyl_dist = view_dist * cyl_hyp_frac; float2 cyl_pos = view_pos * cyl_hyp_frac; return cyl_pos / (cyl_dist - d); } float2 Panini_Generic(float2 view_pos, float d) { // Given // S----------- E--X------- // | ` ~. /,´ // |-- --- Q // | ,/ ` // 1 | ,´/ ` // | ,´ / ´ // | ,´ / ´ // |,` / , // O / // | / , // d | / // | / , // |/ . // P // | ´ // | , ´ // +- ´ // // Have E // Want to find X // // First compute line-circle intersection to find Q // Then project Q to find X float view_dist = 1.0 + d; float view_hyp_sq = view_pos.x * view_pos.x + view_dist * view_dist; float isect_D = view_pos.x * d; float isect_discrim = view_hyp_sq - isect_D * isect_D; float cyl_dist_minus_d = (-isect_D * view_pos.x + view_dist * sqrt(isect_discrim)) / view_hyp_sq; float cyl_dist = cyl_dist_minus_d + d; float2 cyl_pos = view_pos * (cyl_dist / view_dist); return cyl_pos / (cyl_dist - d); } [numthreads(GROUP_SIZE, GROUP_SIZE, 1)] void KMain(uint3 dispatchThreadId : SV_DispatchThreadID) { UNITY_XR_ASSIGN_VIEW_INDEX(dispatchThreadId.z); PositionInputs posInputs = GetPositionInput(float2(dispatchThreadId.xy), _ScreenSize.zw, uint2(GROUP_SIZE, GROUP_SIZE)); float2 uv = posInputs.positionNDC; #if GENERIC float2 proj_pos = Panini_Generic((2.0 * uv - 1.0) * _Params.xy * _Params.w, _Params.z); #else // UNITDISTANCE float2 proj_pos = Panini_UnitDistance((2.0 * uv - 1.0) * _Params.xy * _Params.w); #endif float2 proj_ndc = proj_pos / _Params.xy; float2 coords = proj_ndc * 0.5 + 0.5; if (any(coords < 0.0) || any(coords > 1.0)) { _OutputTexture[COORD_TEXTURE2D_X(posInputs.positionSS)] = 0.0; } else { CTYPE smp = SAMPLE_TEXTURE2D_X_LOD(_InputTexture, sampler_LinearClamp, ClampAndScaleUVForBilinear(coords), 0.0).CTYPE_SWIZZLE; _OutputTexture[COORD_TEXTURE2D_X(posInputs.positionSS)] = smp; } }