আমি কীভাবে একটি মাইনক্রাফ্ট-শৈলীর খেলায় অন্তর্ভুক্তির সাথে ভক্সেল-ভিত্তিক আলো প্রয়োগ করতে পারি?


13

আমি সি # এবং এক্সএনএ ব্যবহার করছি। আলোকসজ্জার জন্য আমার বর্তমান অ্যালগরিদম একটি পুনরাবৃত্ত পদ্ধতি। তবে এটি ব্যয়বহুল , যেখানে প্রতি 8 সেকেন্ডে একটি 8x128x8 অংশ গণনা করা হয়।

  • এমন কি অন্যান্য আলোর পদ্ধতি রয়েছে যা ভেরিয়েবল-অন্ধকারের ছায়া তৈরি করবে?
  • বা পুনরাবৃত্তির পদ্ধতিটি ভাল, এবং সম্ভবত আমি এটি কেবল ভুল করছি?

দেখে মনে হচ্ছে পুনরাবৃত্ত উপাদানগুলি মূলত ব্যয়বহুল (প্রতি অংশের প্রায় 25k ব্লক ধরে যেতে বাধ্য করা হয়)। আমি রে ট্রেসিংয়ের মতো একটি পদ্ধতি ব্যবহার করার বিষয়ে ভাবছিলাম, তবে এটি কীভাবে কাজ করবে তা আমার কোনও ধারণা নেই। আরেকটি জিনিস আমি চেষ্টা করেছিলাম একটি তালিকায় আলোর উত্স সংরক্ষণ করা এবং প্রতিটি ব্লকের জন্য প্রতিটি আলোক উত্সের দূরত্ব পাওয়া এবং এটি সঠিক স্তরে আলোকিত করার জন্য ব্যবহার করা, তবে তারপরে আলোক প্রাচীরের মধ্য দিয়ে যেতে হবে।

আমার বর্তমান পুনরাবৃত্তি কোডটি নীচে is সূর্যরশ্মি এবং টর্চলাইট সাফ করে পুনরায় যুক্ত করার পরে শঙ্কার হালকা স্তর নেই এমন অংশের যে কোনও জায়গা থেকে এটিকে বলা হয়।

world.get___atএটি এমন একটি ফাংশন যা এই অংশের বাইরে ব্লকগুলি পেতে পারে (এটি খণ্ড শ্রেণীর অভ্যন্তরে)। Locationএটি আমার নিজস্ব কাঠামো যা একটি এর মতো Vector3তবে ভাসমান পয়েন্টের মানগুলির পরিবর্তে পূর্ণসংখ্যার ব্যবহার করে। light[,,]খণ্ড জন্য হালকা মানচিত্র।

    private void recursiveLight(int x, int y, int z, byte lightLevel)
    {
        Location loc = new Location(x + chunkx * 8, y, z + chunky * 8);
        if (world.getBlockAt(loc).BlockData.isSolid)
            return;
        lightLevel--;
        if (world.getLightAt(loc) >= lightLevel || lightLevel <= 0)
            return;
        if (y < 0 || y > 127 || x < -8 || x > 16 || z < -8 || z > 16)
            return;
        if (x >= 0 && x < 8 && z >= 0 && z < 8)
            light[x, y, z] = lightLevel;

        recursiveLight(x + 1, y, z, lightLevel);
        recursiveLight(x - 1, y, z, lightLevel);
        recursiveLight(x, y + 1, z, lightLevel);
        recursiveLight(x, y - 1, z, lightLevel);
        recursiveLight(x, y, z + 1, lightLevel);
        recursiveLight(x, y, z - 1, lightLevel);
    }

1
কিছু ভয়ঙ্করভাবে ভুল যদি খণ্ড প্রতি 2 মিলিয়ন ব্লক করছেন হয় - সেখানে বিশেষ করে শুধুমাত্র 8.192 ব্লক আসলে মধ্যে একটি 8 * 128 * 8 খণ্ড। আপনি প্রতিটি ব্লকটি 244 বার দিয়ে যাচ্ছেন এমনটি আপনি কী করতে পারেন? (এটি 255 হতে পারে?)
ডপপেলগ্র্রেনার

1
আমি আমার গণিত ভুল করেছি। দুঃখিত: পি। পরিবর্তন করা হচ্ছে। তবে আপনাকে কেন যেতে হবে তার কারণ যদিও আপনার সেটিংসের চেয়ে কোনও হালকা স্তরের উপর চাপ না দেওয়া পর্যন্ত আপনাকে প্রতিটি ব্লক থেকে "বুদ্বুদ আউট" করতে হবে। এর অর্থ হ'ল আসল আলোর স্তরে হিট হওয়ার আগে প্রতিটি ব্লক 5-10 বার ওভাররাইট হয়ে যায়। 8x8x128x5 = অনেক

2
আপনি কীভাবে আপনার ভক্সেল সংরক্ষণ করছেন? ট্র্যাভারসাল সময়গুলি হ্রাস করা গুরুত্বপূর্ণ।
সামুরসা

1
আপনি কি আপনার আলোক আলগোরিদম পোস্ট করতে পারেন? (আপনি জিজ্ঞাসা করেন আপনি এটি খারাপভাবে করছেন কিনা, আমাদের কোনও ধারণা নেই)
ডপপেলগ্র্রেনার

আমি এগুলিকে "ব্লকস" এর অ্যারে সংরক্ষণ করছি, এবং একটি ব্লকটিতে উপাদানগুলির জন্য একটি এনাম, ভবিষ্যতে ব্যবহারের জন্য একটি মেটাডেটা বাইট রয়েছে।

উত্তর:


6
  1. প্রতিটি আলোতে একটি সুনির্দিষ্ট (ভাসমান পয়েন্ট) অবস্থান থাকে এবং একটি স্কেলার আলোক ব্যাসার্ধ মান দ্বারা নির্ধারিত সীমানা গোলক হয় LR
  2. প্রতিটি ভক্সেলের তার কেন্দ্রে একটি সুনির্দিষ্ট (ভাসমান পয়েন্ট) অবস্থান থাকে, যা আপনি গ্রিডে তার অবস্থান থেকে সহজেই গণনা করতে পারেন।
  3. 8192 ভক্সেলের প্রতিটি একবারে একবার চালান, এবং প্রত্যেকের জন্য, এটি পরীক্ষা করে এন নাইটের প্রতিটি গোলাকৃতির বাউন্ডিং ভলিউমের মধ্যে পড়ে কিনা তা দেখুন |VP - LP| < LR, যেখানে ভিপি হ'ল উত্সের সাথে সম্পর্কিত ভক্সেলের অবস্থান ভেক্টর এবং উত্সের তুলনায় LPআলোর অবস্থান ভেক্টর। প্রতিটি আলোর যার ব্যাসার্ধের বর্তমান ভক্সেল পাওয়া গেছে, আলোর কেন্দ্র থেকে দূরত্বে এটি হালকা ফ্যাক্টর বৃদ্ধি করে |VP - LP|। আপনি যদি সেই ভেক্টরকে স্বাভাবিক করেন এবং তার দৈর্ঘ্যটি পান তবে এটি 0.0-> 1.0 এর মধ্যে থাকবে। একটি ভক্সেল সর্বোচ্চ আলোর স্তরে পৌঁছাতে পারে 1.0 1.0

রানটাইমটি O(s^3 * n)যেখানে sআপনার ভক্সেল অঞ্চলের পাশের দৈর্ঘ্য (128) এবং nএটি হালকা উত্সের সংখ্যা। যদি আপনার আলোর উত্স স্থিতিশীল হয় তবে এটি কোনও সমস্যা নয়। যদি আপনার আলোর উত্সগুলি রিয়েল টাইমে চলে আসে তবে আপনি প্রতিটি শেবাংকে সম্পূর্ণ আপডেটের পুনরায় গণনা না করে কেবল ডেল্টাসে কাজ করতে পারেন।

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


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

মার্টিনসোজকা বিস্তারিত জানার জন্য ধন্যবাদ। হ্যাঁ আরও বুদ্ধিমান বন্যার ভরাটের মতো শোনাচ্ছে। বৈশ্বিক আলোকসজ্জার যেকোন প্রয়াসের সাথে, চতুর অপ্টিমাইজেশনের সাথেও ব্যয়গুলি বেশি থাকে। এই সমস্যাগুলিকে প্রথমে 2D তে চেষ্টা করা ভাল, এবং এগুলি যদি দূর থেকেও ব্যয়বহুল হয় তবে জেনে রাখুন যে আপনার হাতে 3D এ একটি সুনির্দিষ্ট চ্যালেঞ্জ থাকবে have
প্রকৌশলী

4

মাইনক্রাফ্ট নিজেই সূর্যের আলো এইভাবে করে না।

আপনি কেবল উপরে থেকে নীচে পর্যন্ত সূর্যের আলো পূরণ করুন, প্রতিটি স্তর পূর্ববর্তী স্তরে প্রতিবেশী voxels থেকে আলোককে একত্রিত করছে is খুব দ্রুত - একক পাস, কোনও তালিকা, কোনও ডেটা স্ট্রাকচার, কোনও পুনরাবৃত্তি urs

পরের পাসে আপনাকে মশাল এবং অন্যান্য বন্যার বন্যাগুলি যুক্ত করতে হবে।

অভিনব দিকনির্দেশক আলোর প্রচার ইত্যাদি সহ এটি করার জন্য আরও অনেকগুলি উপায় রয়েছে তবে এগুলি স্পষ্টতই ধীরে ধীরে হয় এবং আপনি যদি এই শাস্তি প্রদানের অতিরিক্ত অতিরিক্তবাদে বিনিয়োগ করতে চান তবে আপনাকে খুঁজে বের করতে হবে।


অপেক্ষা করুন, তাহলে মাইনক্রাফ্ট ঠিক কীভাবে এটি করে? আপনি যা বলছিলেন ঠিক তেমনটি পেলাম না ... "প্রতিটি স্তর পূর্ববর্তী স্তরের প্রতিবেশী ভক্সেল থেকে মনোযোগ দিয়ে আলো সংগ্রহ করছে" এর অর্থ কী?

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

1
দয়া করে মনে রাখবেন যে এই পদ্ধতিটি কোনওভাবেই প্রকৃত পদার্থবিজ্ঞানের উপর ভিত্তি করে নয় :) মূল সমস্যাটি হ'ল আপনি মূলত কোনও দিকনির্দেশক আলো (বায়ুমণ্ডলীয় বিচ্ছুরণ) আনুমানিক করার চেষ্টা করছেন এবং একটি সরল তাত্ত্বিকতার সাথে রেডিয়োসিটি বাউন্স করছেন। দেখতে বেশ সুন্দর লাগছে।
বজর্ন ওয়েজেন

3
যে "ঠোঁট" ঝুলছে সে সম্পর্কে কী, সেখানে কীভাবে আলো উঠে যায়? আলো কীভাবে একটি anর্ধ্বমুখী দিকে ভ্রমণ করবে? আপনি যখন কেবল উপরের দিকে যান তবে ওভারহ্যাংগুলি পূরণ করতে আপনি উপরের দিকে ফিরে যেতে পারবেন না। মশাল / অন্যান্য আলোর উত্সও। আপনি এই কিভাবে করবেন? (তারা কেবল নীচে যেতে পারে!)

1
@ ফিলাহার্ট: এখন আমি যখন এটি দেখছিলাম এখন বেশিক্ষণ ছিল, তবে প্রকৃতপক্ষে একটি ন্যূনতম পরিবেষ্টনের আলোক স্তর রয়েছে যা সাধারণত ওভারহ্যাংগুলির নীচের পক্ষে যথেষ্ট যাতে তারা সম্পূর্ণ কালো হয় না। আমি যখন এটি নিজে প্রয়োগ করেছি, তখন ডাউন-> আপ থেকে দ্বিতীয় পাসটি যুক্ত করেছি তবে পরিবেষ্টিত পদ্ধতির তুলনায় আমি সত্যিই কোনও বড় নান্দনিক উন্নতি দেখতে পাইনি। টর্চ / পয়েন্টলাইটগুলি পৃথকভাবে পরিচালনা করতে হবে - আমি মনে করি আপনি যদি কোনও দেয়ালের মাঝখানে টর্চ রাখেন এবং কিছুটা পরীক্ষা করেন তবে আপনি এমসিতে ব্যবহৃত বংশবিস্তার প্যাটার্নটি দেখতে পাবেন। আমার পরীক্ষাগুলিতে, আমি সেগুলি যুক্ত করে একটি পৃথক লাইটফিল্ডে প্রচার করি।
বিজোর ওয়েইন

3

কেউ আপনার নিজের প্রশ্নের উত্তর দিতে বলেছিল যদি আপনি এটি বের করে ফেলেছেন, তাই হ্যাঁ। একটি পদ্ধতি বের করা।

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

এখন ভারী জিনিসগুলির জন্য: 16 টি পাস (প্রতিটি হালকা স্তরের জন্য) সহ পুরো অংশটি যান, এবং যদি এটি 'ইতিমধ্যে পরিবর্তিত' ঠিক চালিয়ে যায় তবে। তারপরে নিজের চারপাশের ব্লকের জন্য হালকা স্তরটি পান। এগুলির সর্বোচ্চ আলো স্তর পান। যদি সেই আলো স্তরটি বর্তমান পাসের আলোর স্তরের সমতুল্য হয় তবে আপনি যে ব্লকটি চালু আছেন বর্তমান স্তরে সেট করুন এবং সেই অবস্থানটির জন্য "ইতিমধ্যে পরিবর্তিত" সেট করুন। চালিয়ে যান।

আমি এর জটিল জটিল জানি, আমি আমার সেরাটি ব্যাখ্যা করার চেষ্টা করেছি। তবে গুরুত্বপূর্ণ ঘটনাটি হ'ল এটি কাজ করে এবং দ্রুত।


2

আমি এমন একটি অ্যালগরিদম প্রস্তাব করব যা সাজানোর মাধ্যমে আপনার মাল্টি-পাস সমাধানটি মূল পুনরাবৃত্তির পদ্ধতির সাথে সংযুক্ত করে, এবং সম্ভবত তাদের উভয়টির চেয়ে বেশ খানিকটা দ্রুত।

আপনার প্রতিটি ব্লক স্তরের জন্য 16 টি তালিকা (বা কোনও ধরণের সংগ্রহ) দরকার হবে। (প্রকৃতপক্ষে, অল্প অল্প তালিকাগুলি ব্যবহার করার জন্য এই অ্যালগরিদমকে অনুকূলিত করার উপায় রয়েছে তবে এইভাবে বর্ণনা করা সহজ)

প্রথমে তালিকাটি সাফ করুন এবং সমস্ত ব্লকের আলোর স্তর শূন্যে সেট করুন এবং তারপরে আপনি আপনার বর্তমান সমাধান হিসাবে হালকা উত্সগুলি আরম্ভ করুন। (বা চলাকালীন) এর পরে, সংশ্লিষ্ট তালিকায় শূন্য-নূরের আলোর স্তর সহ যে কোনও ব্লক যুক্ত করুন।

এখন, হালকা স্তর 16 সহ ব্লকের তালিকায় যান them তাদের সংলগ্ন ব্লকের যদি কোনওেরও কম স্তর 15 এর চেয়ে কম থাকে, তবে তাদের আলোর স্তরটি 15 এ সেট করুন এবং তাদের উপযুক্ত তালিকায় যুক্ত করুন। (যদি তারা ইতিমধ্যে অন্য তালিকায় থাকে তবে আপনি সেগুলি এটিকে সরাতে পারেন, তবে তা না করলেও কোনও ক্ষতি করে না))

তারপরে উজ্জ্বলতার ক্রম হ্রাস করে, অন্যান্য সমস্ত তালিকার জন্য একই পুনরাবৃত্তি করুন। যদি আপনি দেখতে পান যে তালিকার একটি ব্লকের ইতিমধ্যে সেই তালিকায় থাকার চেয়ে তার চেয়ে বেশি আলোর স্তর রয়েছে, তবে আপনি ধরে নিতে পারেন এটি ইতিমধ্যে প্রক্রিয়াজাত ছিল এবং এমনকি তার প্রতিবেশীদের চেক করাও বিরক্ত করে না। (তারপরে, কেবল প্রতিবেশীদের পরীক্ষা করা দ্রুত হতে পারে - এটি কত ঘন ঘন ঘটে তার উপর নির্ভর করে You সম্ভবত আপনি এটি উভয় উপায়েই চেষ্টা করে দেখতে হবে এবং কোন রাস্তাটি দ্রুত is

আপনি লক্ষ করতে পারেন যে তালিকাটি কীভাবে সংরক্ষণ করা উচিত তা আমি নির্দিষ্ট করে নেই; সত্যই সুন্দর কোনও যুক্তিসঙ্গত বাস্তবায়ন এটি করা উচিত, যতক্ষণ না কোনও প্রদত্ত ব্লক সন্নিবেশ করা এবং একটি স্বেচ্ছাসেবক ব্লক বের করা উভয়ই দ্রুত অপারেশন। একটি লিঙ্কযুক্ত তালিকার কাজ করা উচিত, তবে ভেরিয়েবল-দৈর্ঘ্যের অ্যারেগুলির অর্ধেকভাবে শালীন বাস্তবায়নও হবে। আপনার জন্য যা ভাল কাজ করে তা কেবল ব্যবহার করুন।


সংযোজন: আপনার বেশিরভাগ আলো যদি খুব ঘন ঘন সরে না যায় (এবং দেয়ালও দেয় না), প্রতিটি লিট ব্লকের জন্য, আলোক উত্সের জন্য একটি পয়েন্টার যা তার আলোর স্তর নির্ধারণ করে (বা এর একটিতে) তাদের, যদি বেশ কয়েকটি বাঁধা থাকে)। এইভাবে, আপনি বৈশ্বিক আলোক আপডেটগুলি পুরোপুরি সম্পূর্ণ এড়াতে পারবেন: যদি কোনও নতুন আলোক উত্স যুক্ত করা হয় (বা কোনও বিদ্যমান আলোকিত) তবে আপনাকে কেবল তার চারপাশের ব্লকগুলির জন্য একটি একক পুনরাবৃত্ত আলো পাস করতে হবে, যদি কোনওটি সরানো হয় (বা যদি ম্লান), আপনার কেবল সেই ব্লকগুলিকে আপডেট করতে হবে যা এটি দেখায়।

এমনকি আপনি দেয়াল পরিবর্তনগুলিও এইভাবে পরিচালনা করতে পারেন: যখন কোনও প্রাচীর সরিয়ে ফেলা হবে, তখন সেই ব্লকে একটি নতুন পুনরাবৃত্ত আলোকসজ্জা পাস শুরু করুন; যখন একটি যুক্ত করা হয়, তখন সমস্ত ব্লকের জন্য একটি আলোক রেক্যালাক করুন যা নতুন প্রাচীরযুক্ত ব্লকের মতো একই আলোক উত্সকে নির্দেশ করে।

(যদি এক সাথে একাধিক আলোর পরিবর্তন ঘটে - যেমন যদি কোনও আলো সরানো হয়, যা অপসারণ এবং সংযোজন হিসাবে গণনা করা হয় - উপরের অ্যালগরিদমটি ব্যবহার করে আপডেটগুলি এককভাবে একত্রিত করা উচিত Bas মূলত, আপনি সমস্ত আলোর স্তর শূন্য করে যান) অপসারণ করা আলোর উত্সগুলিতে ইঙ্গিত করা ব্লকগুলি, তাদের চারপাশের যে কোনও আলোকিত ব্লক পাশাপাশি কোনও নতুন আলোক উত্স (বা শূন্য অঞ্চলগুলির মধ্যে বিদ্যমান আলোক উত্সগুলি) উপযুক্ত তালিকায় যুক্ত করুন এবং উপরের মত আপডেটগুলি চালান)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.