আমি কীভাবে 2 ডি টপ-ডাউন টাইলস, নির্দেশিত জলের প্রবাহকে রেন্ডার করব?


9

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

নির্দেশাবলী সহ নদীর টাইলগুলির উদাহরণ

গ্রাফিক্যাল স্টাইলের রেফারেন্সের জন্য, আমার খেলাটি বর্তমানে কেমন দেখাচ্ছে তা এখানে:

গ্রাফিকাল স্টাইলের ইন-গেম শট

আমার যা দরকার তা হ'ল নদীর টাইলগুলির প্রত্যেকটিতে প্রবাহিত জলকে সঞ্জীবিত করার জন্য কিছু কৌশল, যাতে প্রবাহটি পার্শ্ববর্তী টাইলগুলিতে মিশ্রিত হয় যাতে টাইলের প্রান্তগুলি দৃশ্যমান হয় না।

আমি পরে যা পেয়েছি তার নিকটতম উদাহরণটি http://www.rug.nl/sociversity-business/centre-for-information-technology/research/hpcv/publications/watershader/ এ বর্ণনা করা হয়েছে তবে আমি বেশ নই বুঝতে পারা যায় যে এতে কী চলছে? আমার নিজের গতিশীল আলো প্রয়োগ করতে শ্যাডার প্রোগ্রামিংয়ের আমার যথেষ্ট পরিমাণে বোঝাপড়া রয়েছে তবে আমি লিঙ্কযুক্ত নিবন্ধে গৃহীত পদ্ধতির কাছাকাছি আসতে পারি না।

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


আপনি কি জল নিজেই জন্য একটি চাক্ষুষ লক্ষ্য আছে? আমি লক্ষ্য করি যে লিঙ্কটি আপনি উল্লেখ করেছেন তা স্পষ্টুলার প্রতিবিম্বের জন্য সাধারণ মানচিত্র ব্যবহার করছে - এমন কিছু যা আপনার প্রদর্শিত ফ্ল্যাট / কার্টুন-স্টাইল শিল্পের দিকের দিক থেকে পুরোপুরি মিশ্রিত নাও হতে পারে। কৌশলটি অন্যান্য স্টাইলের সাথে খাপ খাইয়ে নেওয়ার উপায় রয়েছে তবে আমাদের কিছু গাইডলাইন প্রয়োজন যাতে আমরা কী কী লক্ষ্য নির্ধারণ করতে পারি তা আমাদের জানা উচিত।
ডিএমগ্রিগরি

আপনি আপনার প্রবাহ সমাধানটি কণার জন্য গ্রেডিয়েন্ট হিসাবে ব্যবহার করতে পারেন যা আপনি প্রবাহে ছেড়ে দিয়েছেন। সম্ভবত ব্যয়বহুল, যেমন আপনার প্রচুর প্রয়োজন হবে।
ব্রাম

আমি এটি একটি শেডার দিয়ে সমাধান করব না, আমি এটি সহজ উপায়ে যা বহু শতাব্দী ধরে ব্যবহার করা হয়েছিল, কেবল এটি আঁকুন এবং পানির 8 টি বিভিন্ন অঙ্কন এবং তীরে আঘাতকারী জলের 8 টি বিভিন্ন অঙ্কনও রাখব। তারপরে কোনও রঙের ওভারলে যুক্ত করুন যদি আপনি আলাদা অঞ্চল থাকতে চান এবং ছড়িয়ে ছিটিয়ে পাথর, মাছ বা নদীতে যা কিছুতে এলোমেলোভাবে যোগ করতে চান। বিটিডব্লিউ 8 টির সাথে আমি বোঝাতে চেয়েছি প্রতি 45 ডিগ্রি
ঘোরার জন্য

@ যোশ সাইনারগি আমি চাই নদীর প্রবাহটি 8 দিকের পরিবর্তে যে কোনও দিকে হোক এবং টাইলের কিনারগুলির মধ্যে দৃশ্যমান সীমানা থাকা এড়াতে চাই, সংযুক্ত শেডারে প্রাপ্ত ফলাফলের মতো
রস টেলর-টার্নার

@ ব্র্যাম এটি এমন একটি বিকল্প যা আমি বিবেচনা করতে পারি যে আমি অর্জন করতে পেরেছি, তবে আরও মনে করি এটি কার্যকর করার জন্য খুব বেশি কণার প্রয়োজন হবে, বিশেষত যখন ক্যামেরাটি অনেকটা জুম করা হয়
রস টেলর-টার্নার

উত্তর:


11

আমার কাছে এমন কোনও টাইলস সহজ ছিল না যা বিকৃতির সাথে ভাল লাগছিল, সুতরাং এই কেনে টাইলগুলির সাথে আমি কীভাবে প্রভাব ফেললাম তার একটি সংস্করণ এখানে রয়েছে :

টালিমেপে প্রবাহিত জল দেখাচ্ছে অ্যানিমেশন showing

আমি এর মতো একটি ফ্লোম্যাপ ব্যবহার করছি, যেখানে লাল = ডানদিকে প্রবাহ এবং সবুজ = upর্ধ্বমুখী, হলুদ উভয়ই। প্রতিটি পিক্সেল এক টাইলের সাথে মিলে যায়, নীচে বাম পিক্সেলটি আমার ওয়ার্ল্ড কোঅর্ডিনেট সিস্টেমের (0, 0) এ টাইল হয়।

8x8

এবং এর মতো একটি ওয়েভ প্যাটার্ন টেক্সচার:

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

আমি ইউনিটির এইচএলএসএল / সিজি-স্টাইল সিনট্যাক্সের সাথে সর্বাধিক পরিচিত, সুতরাং আপনার জিএসএসএল প্রসঙ্গে আপনাকে এই শেডারটি কিছুটা মানিয়ে নিতে হবে, তবে এটি করা সহজবোধ্য হওয়া উচিত।

// Colour texture / atlas for my tileset.
sampler2D _Tile;
// Flowmap texture.
sampler2D _Flow;
// Wave surface texture.
sampler2D _Wave;

// Tiling of the wave pattern texture.
float _WaveDensity = 0.5f;
// Scrolling speed for the wave flow.
float _WaveSpeed  = 5.0f;

// Scaling from my world size of 8x8 tiles 
// to the 0...1
float2 inverseFlowmapSize = (float2)(1.0f/8.0f);

struct v2f
{
    // Projected position of tile vertex.
    float4 vertex   : SV_POSITION;
    // Tint colour (not used in this effect, but handy to have.
    fixed4 color    : COLOR;
    // UV coordinates of the tile in the tile atlas.
    float2 texcoord : TEXCOORD0;
    // Worldspace coordinates, used to look up into the flow map.
    float2 flowPos  : TEXCOORD1;
};

v2f vert(appdata_t IN)
{
    v2f OUT;

    // Save xy world position into flow UV channel.
    OUT.flowPos = mul(ObjectToWorldMatrix, IN.vertex).xy;

    // Conventional projection & pass-throughs...
    OUT.vertex = mul(MVPMatrix, IN.vertex);
    OUT.texcoord = IN.texcoord;
    OUT.color = IN.color;

    return OUT;
}

// I use this function to sample the wave contribution
// from each of the 4 closest flow map pixels.
// uv = my uv in world space
// sample site = world space        
float2 WaveAmount(float2 uv, float2 sampleSite) {
    // Sample from the flow map texture without any mipmapping/filtering.
    // Convert to a vector in the -1...1 range.
    float2 flowVector = tex2Dgrad(_Flow, sampleSite * inverseFlowmapSize, 0, 0).xy 
                        * 2.0f - 1.0f;
    // Optionally, you can skip this step, and actually encode
    // a flow speed into the flow map texture too.
    // I just enforce a 1.0 length for consistency without getting fussy.
    flowVector = normalize(flowVector);

    // I displace the UVs a little for each sample, so that adjacent
    // tiles flowing the same direction don't repeat exactly.
    float2 waveUV = uv * _WaveDensity + sin((3.3f * sampleSite.xy + sampleSite.yx) * 1.0f);

    // Subtract the flow direction scaled by time
    // to make the wave pattern scroll this way.
    waveUV -= flowVector * _Time * _WaveSpeed;

    // I use tex2DGrad here to avoid mipping down
    // undesireably near tile boundaries.
    float wave = tex2Dgrad(_Wave, waveUV, 
                           ddx(uv) * _WaveDensity, ddy(uv) * _WaveDensity);

    // Calculate the squared distance of this flowmap pixel center
    // from our drawn position, and use it to fade the flow
    // influence smoothly toward 0 as we get further away.
    float2 offset = uv - sampleSite;
    float fade = 1.0 - saturate(dot(offset, offset));

    return float2(wave * fade, fade);
}

fixed4 Frag(v2f IN) : SV_Target
{
    // Sample the tilemap texture.
    fixed4 c = tex2D(_MainTex, IN.texcoord);

    // In my case, I just select the water areas based on
    // how blue they are. A more robust method would be
    // to encode this into an alpha mask or similar.
    float waveBlend = saturate(3.0f * (c.b - 0.4f));

    // Skip the water effect if we're not in water.
    if(waveBlend == 0.0f)
        return c * IN.color;

    float2 flowUV = IN.flowPos;
    // Clamp to the bottom-left flowmap pixel
    // that influences this location.
    float2 bottomLeft = floor(flowUV);

    // Sum up the wave contributions from the four
    // closest flow map pixels.     
    float2 wave = WaveAmount(flowUV, bottomLeft);
    wave += WaveAmount(flowUV, bottomLeft + float2(1, 0));
    wave += WaveAmount(flowUV, bottomLeft + float2(1, 1));
    wave += WaveAmount(flowUV, bottomLeft + float2(0, 1));

    // We store total influence in the y channel, 
    // so we can divide it out for a weighted average.
    wave.x /= wave.y;

    // Here I tint the "low" parts a darker blue.
    c = lerp(c, c*c + float4(0, 0, 0.05, 0), waveBlend * 0.5f * saturate(1.2f - 4.0f * wave.x));

    // Then brighten the peaks.
    c += waveBlend * saturate((wave.x - 0.4f) * 20.0f) * 0.1f;

    // And finally return the tinted colour.
    return c * IN.color;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.