You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
4.2 KiB
Plaintext

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}
}
}