এইচএলএসএল দিয়ে আমি কীভাবে একটি প্রশস্ত কোণ / ফিশিয়ে লেন্স তৈরি করব?


29

বিভিন্ন চূড়ান্ত বিস্তৃত কোণ লেন্সের প্রভাব অর্জনের জন্য কোন ধারণাগুলি কার্যকর করা দরকার?

সিউডোকোড এবং বিষয়বস্তু পাইপলাইনের বিভিন্ন স্তরের উল্লেখ করে নির্দিষ্ট ব্যাখ্যা, পাশাপাশি উত্স কোড থেকে এইচএলএসএলতে কী তথ্য প্রেরণ করা দরকার তা খুব কার্যকর হবে।

এছাড়াও, প্রশস্ত-কোণ লেন্স এবং ফিশিয়ে প্রয়োগের মধ্যে পার্থক্যগুলি কী?

উত্তর:


37

একটি নিয়মিত লেন্সের মডেলগুলির তুলনায় প্রশস্ত-কোণ লেন্সের আলাদা আচরণ করা উচিত নয়। তাদের কেবল একটি বৃহত্তর FOV রয়েছে ( D3DXMatrixPerspectiveFovLHঅর্থে - আমি ধরে নিচ্ছি যে আপনি ডাইরেক্টএক্স ব্যবহার করছেন), বা বৃহত বাম / ডান এবং নীচে / শীর্ষ মানগুলি (ওপেনগোল glFrustumঅর্থে)।

আমি বিশ্বাস করি সত্যই আকর্ষণীয় অংশটি ফিশিয়ে লেন্সের মডেলিংয়ের মধ্যে রয়েছে। আছে ফিশআই কোয়েক যে আপনি অধ্যয়ন করে নিতে পারে, উৎস দিয়ে আসে।

আসল ফিশিয়ে প্রক্ষেপণ

ফিশিয়ে লেন্সের প্রজেকশনটি অবশ্য উচ্চ-লিনিয়ার। আরও প্রচলিত (আমার জ্ঞানের কাছে যা নজরদারি ক্যামেরায় সীমাবদ্ধ) ধরণের লেন্সের Mমধ্যে, স্থানের একটি বিন্দু একটি ইউনিট গোলার্ধের পৃষ্ঠের দিকে প্রক্ষেপণ করা হয়, তারপরে সেই পৃষ্ঠটি ইউনিট ডিস্কের উপর সমান্তরাল প্রক্ষেপণ হয়:

           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

আরও ফিশিয়ে ম্যাপিং রয়েছে যা আরও আকর্ষণীয় প্রভাব দিতে পারে। এটা আপনার উপর নির্ভর করছে.

আমি এইচএলএসএলতে ফিশিয়ে এফেক্ট বাস্তবায়নের দুটি উপায় দেখতে পাচ্ছি।

পদ্ধতি 1: ভার্টেক্স শ্যাডারে প্রক্ষেপণ সম্পাদন করুন

সুবিধা : কোডটিতে প্রায় কোনও কিছুই পরিবর্তন করার দরকার নেই। টুকরা শেডার অত্যন্ত সহজ। বরং:

...
float4 screenPoint = mul(worldPoint, worldViewProjMatrix);
...

আপনি এর মতো কিছু করেন (সম্ভবত অনেকগুলি সরল করা যেতে পারে):

...
// 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);
...

ত্রুটিগুলি : যেহেতু পুরো রেন্ডারিং পাইপলাইনটি রৈখিক রূপান্তরের জন্য ভাবা হয়েছিল, ফলস্বরূপ প্রক্ষেপণটি অনুভূমিকগুলির জন্য সঠিক, তবে সমস্ত প্রকরণটি ভুল হবে, পাশাপাশি জমিনের স্থানাঙ্কগুলিও ত্রিভুজগুলি ত্রিভুজ হিসাবে প্রদর্শিত হবে যদিও এগুলি বিকৃত প্রদর্শিত হওয়া উচিত।

কর্মক্ষেত্র : আরও ত্রিভুজ মহকুমা সহ, জিপিইউতে একটি পরিশোধিত জ্যামিতি প্রেরণ করে আরও ভাল অনুমানের বিষয়টি গ্রহণযোগ্য হতে পারে। এটি জ্যামিতির শেডারেও করা যেতে পারে তবে ভার্টেক্স শ্যাডারের পরে যেহেতু এই পদক্ষেপটি ঘটে তাই জ্যামিতি শেডারটি বেশ জটিল হবে কারণ এটির নিজস্ব অতিরিক্ত অনুমানগুলি সম্পাদন করতে হবে।

পদ্ধতি 2: টুকরা শ্যাডারে প্রক্ষেপণ সম্পাদন করুন

আরও একটি পদ্ধতি হ'ল প্রশস্ত কোণ প্রক্ষেপণ ব্যবহার করে দৃশ্যটি রেন্ডার করা, তারপরে একটি পূর্ণস্ক্রিন ফ্রেগমেন্ট শেডার ব্যবহার করে ফিশিয়ে এফেক্টটি অর্জন করতে চিত্রটিকে বিকৃত করা।

বিন্দু যদি Mস্থানাঙ্ক হয়েছে (x,y)ফিশআই পর্দায় তার মানে এটা স্থানাঙ্ক ছিল (x,y,z)গোলার্ধ পৃষ্ঠের উপর, সঙ্গে z = sqrt(1-x*x-y*y)। যার অর্থ এটি স্থানাঙ্ক ছিল (ax,ay)একটি FOV সঙ্গে অনুষ্ঠিত আমাদের দৃশ্যে thetaযেমন যে a = 1/(z*tan(theta/2))। (এখানে আমার গণিত সম্পর্কে 100% নিশ্চিত নয়, আমি আজ রাতে আবার পরীক্ষা করব)।

খণ্ড শ্যাডারটি এরকম কিছু হতে পারে:

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

সুবিধা : আপনি পিক্সেলের যথার্থতার কারণে কোনও বিকৃতি ছাড়াই একটি নিখুঁত অভিক্ষেপ পান।

খসড়া : আপনি শারীরিকভাবে পুরো দৃশ্য দেখতে পারবেন না, যেহেতু FOV 180 ডিগ্রি পৌঁছাতে পারে না। এছাড়াও, বৃহত্তর FOV, চিত্রের কেন্দ্রে যথাযথতর খারাপ ... এটি সুনির্দিষ্টভাবে যেখানে আপনি সর্বাধিক নির্ভুলতা চান।

কর্মক্ষেত্র : উদাহরণস্বরূপ 5 বিভিন্ন রেন্ডারিং পাস করে যথাযথ ক্ষতি হ্রাস করা যায় এবং কিউব মানচিত্রের পদ্ধতিতে প্রক্ষেপণ করা যায়। আর একটি খুব সাধারণ কাজটি হ'ল কাঙ্ক্ষিত এফওভিতে চূড়ান্ত চিত্রটি ক্রপ করা - এমনকি লেন্সের নিজের মধ্যে 180 ডিগ্রি এফওভি থাকলেও, আপনি কেবল এটির একটি অংশ রেন্ডার করতে পারেন। একে বলা হয় "ফুল-ফ্রেম" ফিশে (যা কৌতুকপূর্ণভাবে বিদ্রূপযুক্ত, যেহেতু এটি এই ধারণাটি দেয় যে আপনি "পূর্ণ" কিছু পেয়েছেন যখন এটি চিত্রটি সঠিকভাবে কাটাবে)।

(দ্রষ্টব্য: যদি আপনি এটি দরকারী মনে করেন তবে যথেষ্ট পরিমাণে পরিষ্কার না হয়ে থাকেন তবে দয়া করে আমাকে বলুন, আমি এ সম্পর্কে আরও বিস্তারিত নিবন্ধ লিখতে চাই বলে মনে করি)।


খুব দরকারী, এবং আমি আপনাকে আরও আন্তরিকভাবে লিখতে চান এমন আরও নিবন্ধটি স্বাগত জানাব!
স্যার ইয়াকালট

আরও ভাল ফলাফল পেতে উভয় পদ্ধতির একত্রিত করা সম্ভব হবে? প্রথমে সমস্ত কিছু ভিউতে দেখার জন্য ভিএস-তে প্রজেকশন করবেন এবং তারপরে PS তে আনপোজ করুন এবং সঠিক ইউভি এবং সমস্ত কিছুর জন্য আবার প্রকল্প করুন? সঠিকভাবে মূল থেকে আনপ্রোজেক্ট করতে পিএসকে আরও কয়েকটি পরামিতি প্রেরণ করা প্রয়োজন।
ওন্দ্রেজ পেট্রজিলিকা 21'15 21:38

3

এটা হওয়া উচিত z = sqrt(1.0 - in_Point.x * in_Point.x - in_Point.y * in_Point.y), তাই না?

আমার জিএলএসএল বাস্তবায়ন হ'ল:

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D u_texture;
uniform float fovTheta; // FOV's theta

// fisheye
void main (void)
{   
    vec2 uv = v_texCoord - 0.5;
    float z = sqrt(1.0 - uv.x * uv.x - uv.y * uv.y);
    float a = 1.0 / (z * tan(fovTheta * 0.5));
//  float a = (z * tan(fovTheta * 0.5)) / 1.0; // reverse lens
    gl_FragColor = texture2D(u_texture, (uv* a) + 0.5);
}

আরে @ জোশ, কীভাবে fovTheta গণনা করা হয়েছিল?
টম

1
আমি কেবল এই উত্তরটি ফর্ম্যাটটি সামঞ্জস্য করার জন্য সম্পাদনা করেছি, আমি বিশ্বাস করি আপনি সরাসরি @man কে সম্বোধন করতে চান।
জোশ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.