You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
4.2 KiB
134 lines
4.2 KiB
Shader "Hidden/Universal Render Pipeline/PaniniProjection" |
|
{ |
|
HLSLINCLUDE |
|
|
|
#pragma exclude_renderers gles |
|
|
|
#pragma multi_compile_local _GENERIC _UNIT_DISTANCE |
|
#pragma multi_compile _ _USE_DRAW_PROCEDURAL |
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" |
|
#include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Common.hlsl" |
|
|
|
TEXTURE2D_X(_SourceTex); |
|
|
|
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 Frag(Varyings input) : SV_Target |
|
{ |
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); |
|
|
|
#if _GENERIC |
|
float2 proj_pos = Panini_Generic((2.0 * input.uv - 1.0) * _Params.xy * _Params.w, _Params.z); |
|
#else // _UNIT_DISTANCE |
|
float2 proj_pos = Panini_UnitDistance((2.0 * input.uv - 1.0) * _Params.xy * _Params.w); |
|
#endif |
|
|
|
float2 proj_ndc = proj_pos / _Params.xy; |
|
float2 coords = proj_ndc * 0.5 + 0.5; |
|
|
|
return SAMPLE_TEXTURE2D_X(_SourceTex, 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 FullscreenVert |
|
#pragma fragment Frag |
|
ENDHLSL |
|
} |
|
} |
|
}
|
|
|