123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- Shader "Hidden/Universal Render Pipeline/PaniniProjection"
- {
- HLSLINCLUDE
- #pragma multi_compile_local _GENERIC _UNIT_DISTANCE
-
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
- #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/DynamicScalingClamping.hlsl"
- #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
-
- float4 _Params;
-
- // 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);
- }
-
- half4 FragPaniniProjection(Varyings input) : SV_Target
- {
- UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
-
- float2 view_pos = (2.0 * input.texcoord - 1.0) * _Params.xy * _Params.w;
- #if _GENERIC
- float2 proj_pos = Panini_Generic(view_pos, _Params.z);
- #else // _UNIT_DISTANCE
- float2 proj_pos = Panini_UnitDistance(view_pos);
- #endif
-
- float2 proj_ndc = proj_pos / _Params.xy;
- float2 coords = ClampAndScaleUVForBilinear(proj_ndc * 0.5 + 0.5);
-
- return SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, coords);
- }
-
- ENDHLSL
-
- SubShader
- {
- Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline"}
- LOD 100
- ZTest Always ZWrite Off Cull Off
-
- Pass
- {
- Name "Panini Projection"
-
- HLSLPROGRAM
- #pragma vertex Vert
- #pragma fragment FragPaniniProjection
- ENDHLSL
- }
- }
- }
|