您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
136 行
4.1 KiB
136 行
4.1 KiB
Shader "Hidden/Universal Render Pipeline/PaniniProjection"
|
|
{
|
|
Properties
|
|
{
|
|
_MainTex("Source", 2D) = "white" {}
|
|
}
|
|
|
|
HLSLINCLUDE
|
|
|
|
#pragma multi_compile_local _GENERIC _UNIT_DISTANCE
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Common.hlsl"
|
|
|
|
TEXTURE2D_X(_MainTex);
|
|
|
|
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(_MainTex, 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 Frag
|
|
ENDHLSL
|
|
}
|
|
}
|
|
}
|