Geniş açılı bir mercek diğer normal mercek modellerinden farklı davranmamalıdır. Onlar sadece daha büyük bir FOV (yani D3DXMatrixPerspectiveFovLH
- DirectX kullandığınız varsayılmaktadır) veya daha büyük sol / sağ ve alt / üst değerler (OpenGL glFrustum
anlamında) var.
Gerçekten ilginç olan kısmın balık gözü lensin modellenmesinde olduğuna inanıyorum. Orada Balık Gözü Deprem bu kaynağın birlikte geliyordu eğitim görebilirsiniz.
Gerçek balıkgözü izdüşümü
Bununla birlikte, bir balık gözü lensin çıkıntısı doğrusal değildir. Daha yaygın olarak (güvenlik kameraları ile sınırlı olan bilgilerime göre) bir çeşit mercek, M
bir birim yarımkürenin yüzeyine uzayda bir nokta yansıtılır, daha sonra bu yüzey birim disk üzerine paralel bir çıkıntıya uğrar:
M
x M: world position
\ M': projection of M on the unit hemisphere
\ ______ M": projection of M' on the unit disc (= the screen)
M'_x' `-.
,' |\ `.
/ | \ \
/ | \ \
| | \ |
__________|_____|____\_________|_________
M" O 1
Daha ilginç efektler verebilecek başka balıkgözü haritaları vardır. Sana kalmış.
HLSL'de balık gözü etkisini uygulamak için iki yol görebiliyorum.
Yöntem 1: tepe noktası gölgelendiricisi üzerinde izdüşümü gerçekleştir
Avantaj : Neredeyse hiçbir şeyin kodda değiştirilmesi gerekmez. Parça gölgelendirici son derece basittir. Ziyade:
...
float4 screenPoint = mul(worldPoint, worldViewProjMatrix);
...
Böyle bir şey yaparsınız (muhtemelen çok basitleştirilebilir):
...
// This is optional, but it computes the z coordinate we will
// need later for Z sorting.
float4 out_Point = mul(in_Point, worldViewProjMatrix);
// This retrieves the world position so that we can project on
// the hemisphere. Normalise this vector and you get M'
float4 tmpPoint = mul(in_Point, worldViewMatrix);
// This computes the xy coordinates of M", which happen to
// be the same as M'.
out_Point.xy = tmpPoint.xy / length(tmpPoint.xyz);
...
Dezavantajları : Tüm oluşturma boru hattı doğrusal dönüşümler için düşünüldüğünden, sonuçta elde edilen projeksiyon köşeler için kesindir, ancak bütün farklılıklar yanlış olacaktır, ayrıca doku koordinatları ve üçgenler deforme olmuş gibi görünmelerine rağmen yine de üçgenler olarak görünecektir.
Çözümler : GPU'ya daha ince bir alt bölümle rafine bir geometri göndererek daha iyi bir yaklaşım elde etmek kabul edilebilir. Bu aynı zamanda bir geometri gölgelendiricisinde de gerçekleştirilebilir, ancak bu adım köşe gölgelendiriciden sonra gerçekleştiğinden, geometri gölgelendiricisi oldukça karmaşık olur çünkü kendi ek projeksiyonlarını gerçekleştirmek zorunda kalır.
Yöntem 2: projeksiyon parçasını gölgelendirici üzerinde gerçekleştir
Başka bir yöntem, sahneyi geniş açılı bir projeksiyon kullanarak oluşturmak ve ardından bir tam ekran fragman gölgelendirici kullanarak balık gözü efekti elde etmek için görüntüyü bozmaktır.
Nokta balıkgözü ekranında M
koordinatlara sahipse , yarım küre yüzeyinde (x,y)
koordinatlara sahip olduğu anlamına gelir . Bu , bizim sahnemizde böyle bir FOV ile oluşturulan koordinatlarına sahip olduğu anlamına gelir . (Buradaki matematiğimden% 100 emin değil, bu gece tekrar kontrol edeceğim).(x,y,z)
z = sqrt(1-x*x-y*y)
(ax,ay)
theta
a = 1/(z*tan(theta/2))
Dolayısıyla, parça gölgelendirici şöyle bir şey olur:
void main(in float4 in_Point : POSITION,
uniform float u_Theta,
uniform sampler2D u_RenderBuffer,
out float4 out_FragColor : COLOR)
{
z = sqrt(1.0 - in_Point.x * in_Point.x - in_Point.y * in_Point.y);
float a = 1.0 / (z * tan(u_Theta * 0.5));
out_FragColor = tex2D(u_RenderBuffer, (in_Point.xy - 0.5) * 2.0 * a);
}
Avantaj : piksel doğruluğu nedeniyle hiçbir bozulma olmadan mükemmel bir projeksiyon elde edersiniz.
Dezavantaj : FOV 180 dereceye ulaşamadığından tüm sahneyi fiziksel olarak görüntüleyemezsiniz. Ayrıca, FOV ne kadar büyük olursa, görüntünün ortasındaki hassasiyet de o kadar kötü olur ... bu da tam olarak maksimum hassasiyet istediğiniz yerdir.
Geçici Çözümler : Örneğin 5 olmak üzere birçok işleme geçişi gerçekleştirerek hassasiyet kaybı iyileştirilebilir ve projeksiyonu küp harita şeklinde yapabilirsiniz. Çok basit bir diğer geçici çözüm, son görüntüyü istenen FOV'ye basitçe kırpmaktır - lensin kendisi 180 derecelik bir FOV'a sahip olsa bile, bunun yalnızca bir bölümünü oluşturmak isteyebilirsiniz. Buna "full frame" balıkgözü denir (bu aslında biraz ironiktir, çünkü görüntüyü kırparken "tam" bir şey elde ettiğiniz izlenimini verir).
(Not: Eğer bunu yararlı bulduysanız ancak yeterince net görmediyseniz, lütfen bana söyleyin, bunun hakkında daha ayrıntılı bir yazı yazmak istiyorum).