স্ক্যানলাইন সহ জেড-বাফারের জন্য গভীরতা বিভাজন


10

আমাকে আমার নিজস্ব সফ্টওয়্যার 3 ডি রাস্টারাইজার লিখতে হবে এবং এখনও অবধি আমি ত্রিভুজ দ্বারা তৈরি আমার 3 ডি মডেলটিকে 2 ডি স্পেসে প্রজেক্ট করতে সক্ষম হয়েছি:

আমি প্রতিটি ত্রিভুজটির 2 ডি স্পেস উপস্থাপনা পেতে আমার পয়েন্টগুলি ঘোরান, অনুবাদ করি এবং প্রজেক্ট করি। তারপরে, আমি তিনটি ত্রিভুজ পয়েন্ট নিয়েছি এবং আমি ত্রিভুজগুলির কিনারা (বাম এবং ডান) বরাবর সমস্ত পয়েন্ট [x] [y] সন্ধান করতে স্ক্যানলাইন অ্যালগরিদম (লিনিয়ার ইন্টারপোলেশন ব্যবহার করে) প্রয়োগ করি, যাতে আমি ত্রিভুজটি অনুভূমিকভাবে স্ক্যান করতে পারি, সারি সারি সারি, এবং এটি পিক্সেল দিয়ে পূরণ করুন।

এইটা কাজ করে. ব্যতীত আমাকে জেড-বাফারিংও বাস্তবায়ন করতে হবে। এর অর্থ হল যে ত্রিভুজের 3 টি শীর্ষ কোণের ঘোরানো এবং অনুবাদকৃত জেড স্থানাঙ্কগুলি জানার জন্য, আমার স্ক্যানলাইন অ্যালগরিদমের সাথে আমি যে সমস্ত পয়েন্ট পেয়েছি তার জন্য জেড স্থানাঙ্কটি অবশ্যই আমাকে বিভক্ত করতে হবে।

ধারণাটি যথেষ্ট পরিষ্কার বলে মনে হচ্ছে, আমি এই গণনাগুলির সাথে প্রথমে জা এবং জেডবিকে পাই:

var Z_Slope = (bottom_point_z - top_point_z) / (bottom_point_y - top_point_y);
var Za = top_point_z + ((current_point_y - top_point_y) * Z_Slope);

তারপরে প্রতিটি জেডপির জন্য আমি একই প্রান্তিকরণ অনুভূমিকভাবে করব:

var Z_Slope = (right_z - left_z) / (right_x - left_x);
var Zp = left_z + ((current_point_x - left_x) * Z_Slope);

এখানে চিত্র বর্ণনা লিখুন

এবং যদি বর্তমান জেড সেই সূচীতে আগের জেডের তুলনায় দর্শকের কাছাকাছি থাকে তবে রঙটি বাফারে রঙ লিখুন এবং জেড বাফারে নতুন জেডটি লিখুন। (আমার সমন্বিত সিস্টেমটি হল x: বাম -> ডান; y: শীর্ষ -> নীচে; জেড: আপনার মুখ -> কম্পিউটার স্ক্রিন;)

সমস্যাটি হ'ল, এটি বেঁচে আছে। প্রকল্পটি এখানে রয়েছে এবং আপনি যদি "জেড-বাফার্ড" রেডিও বোতামটি নির্বাচন করেন তবে আপনি ফলাফলগুলি দেখতে পাবেন ... ( নোট করুন যে আমি চিত্রশিল্পীর অ্যালগরিদম (কেবলমাত্র তারের ফ্রেম আঁকতে ব্যবহার করি) "জেড-বাফার্ড" মোডে ডিবাগিং উদ্দেশ্যে )

পিএস: আমি এখানে পড়েছি যে আপনি বিভক্ত z = 1/zহওয়ার আগে আপনাকে অবশ্যই জেডগুলি অবশ্যই তাদের উপদানগুলিতে পরিণত করবে (অর্থ )। আমি চেষ্টা করেছিলাম, এবং দেখা যাচ্ছে যে কোনও পরিবর্তন নেই। আমি কী মিস করছি? (যে কেউ স্পষ্ট করে বলতে পারে, অবিকল কোথায় আপনাকে জেডকে 1 / জেডে পরিণত করতে হবে এবং কোথায় এটি ফিরিয়ে আনতে হবে?)

[সম্পাদনা] সর্বাধিক এবং সর্বনিম্ন z মানগুলি কীভাবে পাই সে সম্পর্কে এখানে কিছু তথ্য রয়েছে:

    max z: 1;                  min z: -1;                 //<-- obvious, original z of the vertices of the triangles
    max z: 7.197753398761272;  min z: 3.791703256899924;   //<-- z of the points that were drawn to screen (you know, after rotation, translation), by the scanline with zbuffer, gotten with interpolation but not 1/z.
    max z: 0.2649908532179404; min z: 0.13849507306889008;//<-- same as above except I interpolated 1/z instead of z.
//yes, I am aware that changing z to 1/z means flipping the comparison in the zBuffer check. otherwise nothing gets drawn.

আমি শ্রমসাধ্য ডিবাগিংয়ে যাওয়ার আগে, কেউ কি এখনও নিশ্চিত হতে পারে যে আমার ধারণাটি এখনও সঠিক?

[EDIT2]

আমি জেড-বাফারিংয়ের সমাধান করেছি। দেখা যাচ্ছে যে, অঙ্কন ক্রমটি মোটেও গোলমাল হয়নি। Z স্থানাঙ্কগুলি সঠিকভাবে গণনা করা হচ্ছিল।

সমস্যাটি ছিল আমার ফ্রেমের হার বাড়ানোর প্রয়াসে, আমি স্ক্রিনে প্রকৃত পিক্সেলের পরিবর্তে প্রতি 4 র্থ পিক্সেল 4px / 4px বাক্স আঁকছিলাম। সুতরাং আমি প্রতি পিক্সেলটিতে 16px অঙ্কন করছিলাম তবে তাদের মধ্যে কেবল একটির জন্য জেড বাফার চেক করছি। আমি এ জাতীয় ঠাপ।

টিএল / ডিআর: প্রশ্নটি এখনও দাঁড়িয়েছে: কীভাবে / কেন / কখন আপনি জেডের পরিবর্তে জেডের পারস্পরিক ব্যবহার করতে হবে (1 / জেড হিসাবে)? কারণ এই মুহূর্তে, সবকিছুই কোনওভাবেই কাজ করে। (কোন পার্থক্য লক্ষ্য করা যায় না)।


পুনরায়: "এবং অবশ্যই আমি zBuffer এ যুক্ত করছি, যদি বর্তমান জেড সেই সূচকটিতে আগের মানের তুলনায় দর্শকের কাছাকাছি থাকে।" এটি আমার কাছে পরিষ্কার নয় যে আপনি কী বলেছেন তা আপনি কীভাবে বোঝাতে চেয়েছেন কিন্তু নিশ্চিত করতে চেয়েছিলেন যে আপনি কী বোঝাতে চেয়েছিলেন "যদি বর্তমান জেড সেই সূচীতে পূর্ববর্তী জেডের তুলনায় দর্শকের আরও কাছাকাছি থাকে তবে তারা রঙটি বাফারে রঙ লিখবে এবং লিখবে জেড বাফারকে নতুন জেড "জেড বাফারের উদ্দেশ্য রঙটি ব্লক করা যদি সেই পিক্সেলের কোনও রঙ ইতিমধ্যে ক্যামেরার চোখের আরও কাছে লেখা থাকে।
আলটিরিস

ঐটা ঠিক. দুঃখিত, আমি যখন আমার প্রশ্নটি শব্দ করেছিলাম তখন দেরি হয়ে গেছে। আমি সংশোধন করব।
স্পেকট্রালজাম্প

উত্তর:


5

দ্রুত উত্তর: জেড (এক্স ', ওয়াই') এর লিনিয়ার ফাংশন নয়, তবে 1 / জেড Z যেহেতু আপনি রৈখিকভাবে বিভক্ত করেন, আপনি 1 / জেডের জন্য সঠিক ফলাফল পান তবে জেডের জন্য নয়

আপনি খেয়াল করেন না কারণ যতক্ষণ না Z1 এবং Z2 এর মধ্যে তুলনা সঠিক হয়, ততক্ষণ উভয় মান ভুল হলেও zbuffer সঠিক কাজ করবে। আপনি টেক্সচার ম্যাপিং যুক্ত করার সময় অবশ্যই লক্ষ্য করবেন (এবং আপনার সেই প্রশ্নের উত্তর দেওয়ার জন্য: 1 / জেড, ইউ / জেড এবং ভি / জেড বিভাজন করুন এবং এই মানগুলি থেকে ইউ এবং ভি পুনর্গঠন করুন: ইউ = (ইউ / জেড) / (1 / জেড), ভি = (ভি / জেড) / (1 / জেড)। আপনি আমাকে পরে ধন্যবাদ জানাতে পারবেন)

একটি উদাহরণ. এক টুকরো কাগজ পান। টপ-ডাউন ভিউ, সুতরাং Y স্থানাংকটি ভুলে যান। এক্স অনুভূমিক অক্ষ, জেডটি উল্লম্ব অক্ষ, ক্যামেরাটি (0, 0) এ, প্রক্ষেপণ সমতলটি z = 1।

A (-2, 2) এবং B (2, 4) পয়েন্টগুলি বিবেচনা করুন। বিভাগটি এবি'র মিড পয়েন্ট এম (0, 3)। এ পর্যন্ত সব ঠিকই.

আপনি A কে A ': X' = X / Z = -1 তে প্রজেক্ট করেন, সুতরাং A 'হয় (-1, 1)। তেমনি, বি 'হ'ল (০.৫, ১)। তবে মনে রাখবেন যে এম এর অভিক্ষেপটি (0, 1), যা 'A'B এর মাঝামাঝি নয়। কেন? কারণ বিভাগটির ডান অর্ধেকটি বামার অর্ধেকের চেয়ে ক্যামেরা থেকে অনেক দূরে রয়েছে, তাই এটি আরও ছোট দেখাচ্ছে।

সুতরাং আপনি যদি লিনিয়ার ইন্টারপোলেশন ব্যবহার করে জেড অফ এম এর গণনা করার চেষ্টা করেন তবে কি হবে? dx = (0.5 - -1) = 1.5, dz = (4 - 2) = 2, সুতরাং এম 'এর জন্য যেখানে X' = 0, রৈখিক ইন্টারপোল্টেড জেড zA + (dz / dx) (x - xA) = 2 + (2 / 1.5) (0 - -1) = 2 + 1.333 = 3.3333 - 3 নয়!

কেন? কারণ X 'দিকের প্রতিটি পদক্ষেপের জন্য, আপনি Z পরিমাণে সমান পরিমাণটি সরান না (বা অন্য কথায়, জেড এক্স এর লিনিয়ার ফাংশন নয়)। কেন? আপনি যতটা ডান দিকে যান, বিভাগটি আরও দূরে ক্যামেরা থেকে আসে, সুতরাং একটি পিক্সেল স্থানটিতে একটি দীর্ঘতর দূরত্ব উপস্থাপন করে।

পরিশেষে, আপনি যদি 1 / Z পরিবর্তে পৃথক করে থাকেন তবে কি হবে? প্রথমে আপনি A এবং B তে 1 / Z গণনা করুন যথাক্রমে 0.5 এবং 0.25। তারপরে আপনি বিভক্ত করুন: dx = (0.5 - -1) = 1.5, dz = (0.25 - 0.5) = -0.25, সুতরাং এক্স '= 0 এ আপনি 1 / জেড = 0.5 + (-0.25 / 1.5) * (0 - -1) = 0.3333। তবে এটি 1 / জেড তাই জেডের মান হুবহু ... 3, এটি হওয়া উচিত।

হ্যাঁ, গণিত দুর্দান্ত।


1
ওহ, এবং "কখন" সম্পর্কিত: ত্রিভুজটি রাস্টারাইজ করা শুরু করার আগে 1 / জেড মানগুলি গণনা করুন (উদাহরণস্বরূপ উল্লম্ব লুপের ঠিক আগে), যাতে আপনি স্ক্যানলাইনের বাম এবং ডানদিকে 1 / Z জড়িত হন get এই রৈখিকভাবে ইন্টারপোল্ট করুন (আবার 1 / জেড করবেন না - ইন্টারপোল্টেড মানগুলি ইতিমধ্যে 1 / জেড!), এবং জবফারটি পরীক্ষা করার আগে রূপান্তরটি পূর্বাবস্থায় ফিরিয়ে আনুন।
ggambett

1
এবং অবশেষে, কেন। একটি প্লেন (যেখানে ত্রিভুজ এম্বেড করা আছে) হ'ল এক্স + বাই + সিজেড + ডি = 0. জেড স্পষ্টতই (x, y) এর রৈখিক কাজ। আপনি তাই x '= x / z এবং y' = y / z প্রকল্প। সেখান থেকে, x = x'z এবং y = y'z। আপনি যদি এটিকে আসল সমীকরণে প্রতিস্থাপন করেন তবে আপনি অক্ষ + বি'এক্স + সিজেড + ডি = ০ পাবেন Now (x ', y') এর তবে 1 / z হ'ল (অক্ষ '+ বাই' + সি) /-ডি, যা (x ', y') এর লিনিয়ার ফাংশন।
ggambett

1
আপনি জানেন, আমি বেশ কয়েকটি নিবন্ধ এবং কোর্স পড়েছি এবং সেগুলির কোনওটিই আপনার উত্তর হিসাবে পুরোপুরি পরিষ্কার ছিল না। উত্তরোত্তর জন্য, আমি আরও নোট করব যে "U" এবং "V" অক্ষরগুলি 2D টেক্সচারের অক্ষগুলি বোঝায় কারণ "X", "Y" এবং "Z" ইতিমধ্যে মডেলটিতে 3 ডি অবজেক্টের অক্ষগুলি বোঝাতে ব্যবহৃত হয়েছে স্পেস। ইউভি টেক্সচারগুলি এমন বহুভুজকে অনুমতি দেয় যা কোনও চিত্রের রঙ দিয়ে আঁকা একটি 3 ডি অবজেক্ট তৈরি করে। " - উইকিপিডিয়া - ইউভি ম্যাপিং
স্পেকট্রালজাম্প

এটা শুনে আনন্দিত হলাম. আমি প্রকৃতপক্ষে পূর্বের জীবনে কম্পিউটার
গ্রাফিকগুলি শিখিয়েছিলাম

অনেক অনেক ধন্যবাদ - আমি এই সম্পর্কে সর্বদা কৌতূহলী ছিলাম - এবং আমি কখনই এর থেকে আরও ভাল উত্তর পেতে পারতাম কিনা তা আমি জানি না! +1
কোডস্মিত
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.