আমি কীভাবে একটি ভক্সেল ইঞ্জিনে আলো প্রয়োগ করতে পারি?


15

আমি টেরিন ইঞ্জিনের মতো এমসির তৈরি করছি, এবং আমি ভেবেছি যে আলো আলোকিত করা পুরোপুরি সুন্দর দেখায় problem সমস্যাটি হ'ল যে ব্লকটি যখন আলোকিত করে সেখানে স্থাপন করা হয় তখন ব্লকগুলি সঠিকভাবে জ্বালানো হয় না (নীচে স্ক্রিনশটগুলি দেখুন) পৃষ্ঠায়

এখনও অবধি আমি মাইনক্রাফ্টের "ব্লকী" আলো প্রয়োগ করতে চাই সুতরাং আমি একটি ভার্টেক্স ফরমেট তৈরি করেছি:

 struct VertexPositionTextureLight
    {
        Vector3 position;
        Vector2 textureCoordinates;
        float light;

        public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
        (
            new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
            new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
            new VertexElement(sizeof(float) * 5, VertexElementFormat.Single, VertexElementUsage.TextureCoordinate, 1)
        );

        public VertexPositionTextureLight(Vector3 position, Vector3 normal, Vector2 textureCoordinate, float light)
        {
            // I don't know why I included normal data :)
            this.position = position;
            this.textureCoordinates = textureCoordinate;
            this.light = light;
        }
    }

আমার ধারণা আমি আলো প্রয়োগ করতে চাইলে প্রতিটি প্রান্তের জন্য আমাকে একটি আলো নির্দিষ্ট করতে হবে ... এবং এখন আমার প্রভাব ফাইলে আমি সেই মানটি নিতে এবং সেই অনুসারে ভার্টেক্সটি আলোকিত করতে সক্ষম হতে চাই:

float4x4 World;
float4x4 Projection;
float4x4 View;

Texture Texture;

sampler2D textureSampler = sampler_state  {
    Texture = <Texture>;
    MipFilter = Point;
    MagFilter = Point;
    MinFilter = Point;
    AddressU = Wrap;
    AddressV = Wrap;
};

struct VertexToPixel  {
    float4 Position     : POSITION;
    float4 TexCoords    : TEXCOORD0;
    float4 Light        : TEXCOORD01;
};

struct PixelToFrame  {
    float4 Color        : COLOR0;
};

VertexToPixel VertexShaderFunction(float4 inPosition : POSITION, float4 inTexCoords : TEXCOORD0, float4 light : TEXCOORD01)  {
    VertexToPixel Output = (VertexToPixel)0;

    float4 worldPos = mul(inPosition, World);
    float4 viewPos = mul(worldPos, View);

    Output.Position = mul(viewPos, Projection);
    Output.TexCoords = inTexCoords;
    Output.Light = light;

    return Output;
}

PixelToFrame PixelShaderFunction(VertexToPixel PSIn)  {
    PixelToFrame Output = (PixelToFrame)0;

    float4 baseColor = 0.086f;
    float4 textureColor = tex2D(textureSampler, PSIn.TexCoords);
    float4 colorValue = pow(PSIn.Light / 16.0f, 1.4f) + baseColor;

    Output.Color = textureColor;

    Output.Color.r *= colorValue;
    Output.Color.g *= colorValue;
    Output.Color.b *= colorValue;
    Output.Color.a = 1;

    return Output;
}

technique Block  {
    pass Pass0  {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

VertexToPixel VertexShaderBasic(float4 inPosition : POSITION, float4 inTexCoords : TEXCOORD0)  {
    VertexToPixel Output = (VertexToPixel)0;

    float4 worldPos = mul(inPosition, World);
    float4 viewPos = mul(worldPos, View);

    Output.Position = mul(viewPos, Projection);
    Output.TexCoords = inTexCoords;

    return Output;
}

PixelToFrame PixelShaderBasic(VertexToPixel PSIn)  {
    PixelToFrame Output = (PixelToFrame)0;

    Output.Color = tex2D(textureSampler, PSIn.TexCoords);

    return Output;
}


technique Basic  {
    pass Pass0  {
        VertexShader = compile vs_2_0 VertexShaderBasic();
        PixelShader = compile ps_2_0 PixelShaderBasic();
    }
}

এবং আমি কীভাবে আলো প্রয়োগ করি তার একটি উদাহরণ:

            case BlockFaceDirection.ZDecreasing:
                light = world.GetLight((int)(backNormal.X + pos.X), (int)(backNormal.Y + pos.Y), (int)(backNormal.Z + pos.Z));

                SolidVertices.Add(new VertexPositionTextureLight(bottomRightBack, backNormal, bottomLeft, light));
                SolidVertices.Add(new VertexPositionTextureLight(bottomLeftBack, backNormal, bottomRight, light));
                SolidVertices.Add(new VertexPositionTextureLight(topRightBack, backNormal, topLeft, light));
                SolidVertices.Add(new VertexPositionTextureLight(topLeftBack, backNormal, topRight, light));
                AddIndices(0, 2, 3, 3, 1, 0);
                break;

এবং সর্বোপরি এখানে আলগোরিদিম যা সবগুলি গণনা করে:

    public void AddCubes(Vector3 location, float light)
    {
        AddAdjacentCubes(location, light);
        Blocks = new List<Vector3>();
    }

    public void Update(World world)
    {
        this.world = world;
    }

    public void AddAdjacentCubes(Vector3 location, float light)
    {
        if (light > 0 && !CubeAdded(location))
        {
            world.SetLight((int)location.X, (int)location.Y, (int)location.Z, (int)light);
            Blocks.Add(location);

            // Check ajacent cubes
            for (int x = -1; x <= 1; x++)
            {
                for (int y = -1; y <= 1; y++)
                {
                    for (int z = -1; z <= 1; z++)
                    {
                        // Make sure the cube checked it not the centre one
                        if (!(x == 0 && y == 0 && z == 0))
                        {
                            Vector3 abs_location = new Vector3((int)location.X + x, (int)location.Y + y, (int)location.Z + z);

                            // Light travels on transparent block ie not solid
                            if (!world.GetBlock((int)location.X + x, (int)location.Y + y, (int)location.Z + z).IsSolid)
                            {
                                AddAdjacentCubes(abs_location, light - 1);
                            }
                        }
                    }
                }
            }

        }
    }

    public bool CubeAdded(Vector3 location)
    {
        for (int i = 0; i < Blocks.Count; i++)
        {
            if (location.X == Blocks[i].X &&
                location.Y == Blocks[i].Y &&
                location.Z == Blocks[i].Z)
            {
                return true;
            }
        }

        return false;
    }

কোন পরামর্শ এবং সহায়তা অনেক প্রশংসা করা হবে

স্ক্রিনশটস ভূখণ্ডের উপরের অংশে নিদর্শনগুলি দেখুন এবং কীভাবে কেবল বাম অংশটি আংশিকভাবে আলোকিত হয় ... আলোতে চেষ্টা 1 কিছু কারণে ঘনক্ষেত্রের কয়েকটি নির্দিষ্ট অংশ জ্বলানো হচ্ছে এবং এটি জমিটি আলোকিত করে না আলোতে চেষ্টা 2

আগের আরেকটি উদাহরণ

আমার সমস্যা খুঁজে বের! সেই ব্লকটি ইতিমধ্যে প্রজ্জ্বলিত ছিল কিনা এবং তা যদি কোন ডিগ্রীতে ছিল কিনা তা পরীক্ষা করছিলাম না (যদি এটি কম আলো হয় তবে এটি উচ্চতর হয়)

    public void DoLight(int x, int y, int z, float light)
    {
        Vector3 xDecreasing = new Vector3(x - 1, y, z);
        Vector3 xIncreasing = new Vector3(x + 1, y, z);
        Vector3 yDecreasing = new Vector3(x, y - 1, z);
        Vector3 yIncreasing = new Vector3(x, y + 1, z);
        Vector3 zDecreasing = new Vector3(x, y, z - 1);
        Vector3 zIncreasing = new Vector3(x, y, z + 1);

        if (light > 0)
        {
            light--;

            world.SetLight(x, y, z, (int)light);
            Blocks.Add(new Vector3(x, y, z));

            if (world.GetLight((int)yDecreasing.X, (int)yDecreasing.Y, (int)yDecreasing.Z) < light &&
                world.GetBlock((int)yDecreasing.X, (int)yDecreasing.Y, (int)yDecreasing.Z).BlockType == BlockType.none)
                DoLight(x, y - 1, z, light);
            if (world.GetLight((int)yIncreasing.X, (int)yIncreasing.Y, (int)yIncreasing.Z) < light &&
                world.GetBlock((int)yIncreasing.X, (int)yIncreasing.Y, (int)yIncreasing.Z).BlockType == BlockType.none)
                DoLight(x, y + 1, z, light);
            if (world.GetLight((int)xDecreasing.X, (int)xDecreasing.Y, (int)xDecreasing.Z) < light &&
                world.GetBlock((int)xDecreasing.X, (int)xDecreasing.Y, (int)xDecreasing.Z).BlockType == BlockType.none)
                DoLight(x - 1, y, z, light);
            if (world.GetLight((int)xIncreasing.X, (int)xIncreasing.Y, (int)xIncreasing.Z) < light &&
                world.GetBlock((int)xIncreasing.X, (int)xIncreasing.Y, (int)xIncreasing.Z).BlockType == BlockType.none)
                DoLight(x + 1, y, z, light);
            if (world.GetLight((int)zDecreasing.X, (int)zDecreasing.Y, (int)zDecreasing.Z) < light &&
                world.GetBlock((int)zDecreasing.X, (int)zDecreasing.Y, (int)zDecreasing.Z).BlockType == BlockType.none)
                DoLight(x, y, z - 1, light);
            if (world.GetLight((int)zIncreasing.X, (int)zIncreasing.Y, (int)zIncreasing.Z) < light &&
                world.GetBlock((int)zIncreasing.X, (int)zIncreasing.Y, (int)zIncreasing.Z).BlockType == BlockType.none)
                DoLight(x, y, z + 1, light);
        }
    }

উপরের কাজগুলি যথেষ্ট পরিমাণে, কেউ কীভাবে জানতে পারবেন কীভাবে আমি এটিকে আরও পারফর্মেন্স দক্ষ করে তুলব?



একটি দুর্দান্ত প্রশ্ন, তবে এটি বেশ কয়েকটি বিদ্যমান প্রশ্নের সদৃশ ... গেমদেভ.স্ট্যাকেক্সেঞ্জার / প্রশ্নস
টিম হল্ট

উত্তর:


17

আমি এর অনুরূপ কিছু বাস্তবায়ন করেছি। আমি আমার ব্লগে এটি সম্পর্কে একটি পোস্ট লিখেছিলাম: byte56.com/2011/06/a-light-post । তবে আমি এখানে আরও কিছু বিশদে যাব।

অন্য উত্তরে লিঙ্কযুক্ত কোডফ্লো নিবন্ধটি বেশ আকর্ষণীয়। আমি যা বুঝতে পারি তা থেকে, মাইনক্রাফ্ট তার আলোকসজ্জা কীভাবে তা করে না। মাইনক্রাফ্ট আলো আরও সেলুলার অটোমেটা তবে traditionalতিহ্যগত আলোর উত্স।

আমি ধরে নিয়েছি আপনি এমসির জলের প্রবাহের সাথে পরিচিত। এমসিতে আলোকসজ্জা মূলত একই জিনিস। আমি আপনাকে একটি সহজ উদাহরণ দিয়ে যেতে হবে।

এখানে কিছু বিষয় মনে রাখা উচিত।

  • আমরা কিউবগুলির একটি তালিকা রাখতে যাচ্ছি যাতে তাদের আলোকিত মানগুলি পরীক্ষা করা প্রয়োজন
  • কেবল স্বচ্ছ কিউব এবং হালকা নির্গত কিউবের আলোর মান থাকে have

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

এটি আলোর মোটামুটি সহজ ব্যাখ্যা। আমি কিছুটা আরও উন্নত কিছু করেছি, তবে আমি একই প্রাথমিক নীতি দিয়ে শুরু করেছি। এটি এটি যা উত্পাদন করে তার একটি উদাহরণ:

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

এখন আপনি আপনার সমস্ত হালকা তথ্য সেট আছে। আপনি যখন নিজের শীর্ষগুলিগুলির জন্য রঙের মান তৈরি করছেন, আপনি এই উজ্জ্বলতার ডেটাটি উল্লেখ করতে পারেন। আপনি এরকম কিছু করতে পারেন (যেখানে আলোক 0 এবং 15 এর মধ্যে একটি মান হয়):

float baseColor = .086f;
float colorValue = (float) (Math.pow(light / 16f, 1.4f) + baseColor );
return new Color(colorValue, colorValue, colorValue, 1);

মূলত আমি হালকা মান 0 থেকে 1 থেকে 1.4f এর পাওয়ারে নিয়ে যাচ্ছি এটি আমাকে লিনিয়ার ফাংশনের চেয়ে কিছুটা গাer় রঙের ডার্ক দেয়। আপনার রঙের মানটি কখনই 1 এর উপরে না যায় তা নিশ্চিত করুন I তারপরে সেই অতিরিক্তটিকে বেসে স্থানান্তরিত করলাম যাতে আমি সবসময় একটু টেক্সচার থাকি এবং খাঁটি কালোভাব না।

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

সম্পাদনা

কোনও মুখের জন্য আলো পেতে, আপনি মুখের স্বাভাবিকের দিকের দিকে ঘনক্ষনটি তাকান। উদাহরণস্বরূপ, কিউবের শীর্ষ মুখটি উপরের কিউব থেকে হালকা তথ্য পায়।

সম্পাদনা 2

আমি আপনার কয়েকটি প্রশ্নের সমাধান করার চেষ্টা করব।

সুতরাং আমি কি করব এই ক্ষেত্রে পুনরাবৃত্তি মত কিছু?

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

এছাড়াও কিভাবে আলগোরিদিম "হালকা নীচে" হবে?

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

আমি কীভাবে কেবল একক মুখের জন্য আলোক নির্দিষ্ট করব?

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

কোডের নমুনা?

নাঃ।


@ বাইট 56 "খণ্ডগুলি" জুড়ে কাজ করতে এই অ্যালগরিদমকে কীভাবে অনুবাদ করতে হয় তা জানতে আগ্রহী।
gopgop

আমি প্রতিবেশী অনুযায়ী খণ্ডের প্রতিটি পক্ষকে আপডেট করার এবং তারপরে সমস্ত পরিবর্তিত ব্লকগুলি ব্লকের তালিকায় পরিবর্তন করার জন্য
ভেবেছিলাম

@gopgop মন্তব্যগুলি আলোচনার জায়গা নয়। আপনি কিছু সময় আড্ডায় আমাকে খুঁজে পেতে পারেন। বা সেখানকার অন্যান্য লোকদের সাথে এটি আলোচনা করুন।
মাইকেলহাউস

4

নীচের নিবন্ধটি পড়ুন কারণ এটি আপনাকে যা চাচ্ছে তার অনেক তথ্য দেওয়া উচিত give আলোকপাত সম্পর্কে অনেকগুলি বিভাগ রয়েছে তবে বিশেষত পরিবেষ্টনের অন্তর্ভুক্তি, পর্যবেক্ষক আলো এবং হালকা সংগ্রহ সম্পর্কিত বিভাগগুলি পড়ুন:

http://codeflow.org/entries/2010/dec/09/minecraft-like-rendering-experiments-in-opengl-4/

তবে আপনার প্রশ্নের মূলটির উত্তর দেওয়ার চেষ্টা করছি:

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

    বা ...

    রঙ যুক্ত করার পরে, ফলাফলটি ক্ল্যাম্পিংয়ের পরিবর্তে (অর্থাত্ রঙের প্রতিটি উপাদানকে 0 এবং 1 এর মধ্যে চাপিয়ে দেওয়া) পরিবর্তে ফলাফলটি স্কেল করুন - তিনটি উপাদানগুলির মধ্যে কোনটি (আরজিবি) বৃহত্তম এটি আবিষ্কার করুন এবং সেগুলি দিয়ে সমস্তটি ভাগ করুন। এই পদ্ধতিটি রঙের মূল বৈশিষ্ট্যগুলি আরও ভালভাবে সংরক্ষণ করে।

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