UnityGame/Library/PackageCache/com.unity.render-pipelines.universal/Shaders/PostProcessing/PaniniProjection.shader
2024-10-27 10:53:47 +03:00

131 lines
4.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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