মহাকাশ নিদর্শন থেকে বায়ুমণ্ডলীয় বিক্ষিপ্ত আকাশ


20

আমি মহাকাশ থেকে কোনও গ্রহের বায়ুমণ্ডলীয় বিস্তারণ বাস্তবায়নের প্রক্রিয়াধীন। আমি শন ও'নিলের শেডারগুলি http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html থেকে ব্যবহার করছি একটি শুরুর পয়েন্ট হিসাবে ।

এখানে যেমন গ্রাউন্ডফ্রومস্পেস শ্যাডারের বিপরীতে স্কাইফ্র্যামস্পেস শেডারের সাথে বাদে আমার সাথে fCameraAngle সম্পর্কিত একই সমস্যা রয়েছে: http://www.gamedev.net/topic/621187-sean-oneils- /

fCameraAngle = 1অভ্যন্তরীণ লুপটি ব্যবহার না করার সময় আমি স্পেস শেডার থেকে আকাশের সাথে অদ্ভুত শিল্পকর্মগুলি পাই । এই নিদর্শনগুলির কারণ কী? যখন fCameraAngle 1 সীমাবদ্ধ করা হয় তখন নিদর্শনগুলি অদৃশ্য হয়ে যায় আমি ও'নিলের স্যান্ডবক্সে উপস্থিত রঙ্গকেরও অভাব বোধ করি ( http://sponeil.net/downloads.htm )

ক্যামেরার অবস্থান এক্স = 0, ওয়াই = 0, জেড = 500। বামদিকে গ্রাউন্ডফ্রোমস্পেস, ডানদিকে স্কাইফ্রোমস্পেস। এখানে চিত্র বর্ণনা লিখুন

ক্যামেরার অবস্থান এক্স = 500, ওয়াই = 500, জেড = 500। বামদিকে গ্রাউন্ডফ্রোমস্পেস, ডানদিকে স্কাইফ্রোমস্পেস। এখানে চিত্র বর্ণনা লিখুন

আমি খুঁজে পেয়েছি যে উত্সটি নির্ভর করে ক্যামেরার কোণটি খুব আলাদাভাবে পরিচালিত হয়েছে:

আসল শেডগুলিতে স্কাইফ্রোমস্পেসশেদার ক্যামেরার কোণটি হিসাবে গণনা করা হয়:

float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;

যেখানে স্পেস শেডার থেকে গ্রাউন্ডে ক্যামেরা কোণটি গণনা করা হয়:

float fCameraAngle = dot(-v3Ray, v3Pos) / length(v3Pos);

তবে রশ্মিকে অবহেলা করে বিভিন্ন উত্স অনলাইন টিঙ্কার। কেন?

এখানে একটি সি # উইন্ডোজ.ফর্ম প্রকল্প রয়েছে যা সমস্যাটি দেখায় এবং আমি চিত্রগুলি উত্পন্ন করতে ব্যবহার করেছি: https://github.com/ollipekka/At વા্যোসোথেরিকস্যাকটারিংটেষ্ট /

হালনাগাদ: স্ক্যানসিপিইউ প্রকল্প থেকে ও'নিলের সাইটে পাওয়া গিয়েছি যে ক্যামেরাটি ছায়াচ্ছন্ন হওয়ার পরে ক্যামেরা রেডটি অগ্রাহ্য করা হয় যাতে ছড়িয়ে ছিটিয়ে থাকা ক্যামেরায় স্থান নির্ণয় করা হয়।

রশ্মির দিক পরিবর্তন করা প্রকৃতপক্ষে নিদর্শনগুলিকে সরিয়ে দেয়, তবে এখানে চিত্রিত হিসাবে অন্যান্য সমস্যার পরিচয় দেয়:

ক্যামেরা কোণে নেতিবাচক রশ্মি

তদ্ব্যতীত, স্ক্যাটারসিপিইউ প্রকল্পে ও'নিল এমন পরিস্থিতিতে রক্ষা করে যেখানে আলোর জন্য অপটিকাল গভীরতা শূন্যের চেয়ে কম থাকে:

float fLightDepth = Scale(fLightAngle, fScaleDepth);

if (fLightDepth < float.Epsilon)
{
    continue;
}

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

এই আপডেটে পরিবর্তনগুলি প্রতিবিম্বিত করতে গিথুব প্রকল্প আপডেট করা হয়েছে।


1
আমি আপনার কোড অকর্মা এবং সাহায্য করার চেষ্টা ভালোবাসতাম, কিন্তু এটা বনাম 2012 জন্য XNA ইনস্টল করতে আমি বনাম 2010 প্রয়োজন প্রদর্শিত হবে ...

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

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

উত্তর:


1

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

// Inited in code
float innerRadius = sphere.Radius;
float outerRadius = innerRadius*1.025f;
float scale = 1.0f/(outerRadius - innerRadius);
float scaleDepth = outerRadius - innerRadius;
float scaleOverScaleDepth = scale/scaleDepth;

Vector4 invWavelength = new Vector4(
    (float) (1.0/Math.Pow(wavelength.X, 4.0)),
    (float) (1.0/Math.Pow(wavelength.Y, 4.0)),
    (float) (1.0/Math.Pow(wavelength.Z, 4.0)),
    1);

float ESun = 15.0f;
float kr = 0.0025f;
float km = 0.0015f;
float g = -0.95f;
float g2 = g * g;
float krESun = kr * ESun;
float kmESun = km * ESun;
float epkr4Pi = epkr4Pi = (float)(kr * 4 * Math.PI)
float epkm4Pi = epkr4Pi = (float)(kr * 4 * Math.PI)

এই শেডার ছিল:

struct AtmosphereVSOut
{
    float4 Position : POSITION;
    float3 t0 : TEXCOORD0;
    float3 c0 : TEXCOORD1; // The Rayleigh color
    float3 c1 : TEXCOORD2; // The Mie color
    float4 LightDirection : TEXCOORD3;
};

// The scale equation calculated by Vernier's Graphical Analysis
float expScale (float fCos)
{
    //float x = 1.0 - fCos;
    float x = 1 - fCos;
    return scaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));

}
// Calculates the Mie phase function
float getMiePhase(float fCos, float fCos2, float g, float g2)
{
    return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(1.0 + g2 - 2.0*g*fCos, 1.5);
}

// Calculates the Rayleigh phase function
float getRayleighPhase(float fCos2)
{
    return 0.75 + (1.0 + fCos2);
}

// Returns the near intersection point of a line and a sphere
float getNearIntersection(float3 vPos, float3 vRay, float fDistance2, float fRadius2)
{
    float B = 2.0 * dot(vPos, vRay);
    float C = fDistance2 - fRadius2;
    float fDet = max(0.0, B*B - 4.0 * C);
    return 0.5 * (-B - sqrt(fDet));
}

AtmosphereVSOut
AtmosphereFromSpaceVS(float4 vPos : POSITION )
{
    // Multiply the camera position vector in world space by the 
    // World Inverse matrix so that it gets transformed to
    // object space coordinates
    float4 vEyePosInv = mul(vEyePos, mWorldInverse);

    // Compute a ray from the vertex to the camera position
    float3 vRay = vPos - vEyePosInv.xyz;

    // Transform the Light Position to object space and use
    // the result to get a ray from the position of the light
    // to the vertex. This is our light direction vector
    // which has to be normalized.
    float4 vLightDir = mul(vLightPosition,mWorldInverse) - vPos;
    vLightDir.xyz = normalize(vLightDir.xyz);
    vLightDir.w = 1.0;

    // From the vRay vector we can calculate the 
    // "far" intersection with the sphere
    float fFar = length (vRay);
    vRay /= fFar;

    // But we have to check if this point is obscured by the planet
    float B = 2.0 * dot(vEyePosInv, vRay);
    float C = cameraHeight2 - (innerRadius*innerRadius);
    float fDet = (B*B - 4.0 * C);

    if (fDet >= 0)
    {
        // compute the intersection if so
        fFar = 0.5 * (-B - sqrt(fDet));
    }

    // Compute the near intersection with the outer sphere
    float fNear = getNearIntersection (vEyePosInv, vRay, cameraHeight2, outerRadius2);

    // This is the start position from which to compute how
    // the light is scattered
    float3 vStart = vEyePosInv + vRay * fNear;
    fFar -= fNear;

    float fStartAngle = dot (vRay, vStart) / outerRadius;
    float fStartDepth = exp (scaleOverScaleDepth * (innerRadius - cameraHeight));
    float fStartOffset = fStartDepth * expScale (fStartAngle);
    float fSampleLength = fFar / samples;
    float fScaledLength = fSampleLength * scale;
    float3 vSampleRay = vRay * fSampleLength;
    float3 vSamplePoint = vStart + vSampleRay * 0.5f;

    // Now we have to compute each point in the path of the
    // ray for which scattering occurs. The higher the number
    // of samples the more accurate the result.
    float3 cFrontColor = float3 (0,0,0);
    for (int i = 0; i < samples; i++)
    {
        float fHeight = length (vSamplePoint);
        float fDepth = exp (scaleOverScaleDepth * (innerRadius - fHeight));
        float fLightAngle = dot (vLightDir, vSamplePoint) / fHeight;
        float fCameraAngle = dot(-vRay, vSamplePoint) / fHeight;
        float fScatter = (fStartOffset + fDepth * (expScale (fLightAngle) - expScale (fCameraAngle)));

        float3 cAttenuate = exp (-fScatter * (vInvWavelength.xyz * kr4PI + km4PI));

        cFrontColor += cAttenuate * (fDepth * fScaledLength);
        vSamplePoint += vSampleRay;
    }

    // Compute output values
    AtmosphereVSOut Out;

    // Compute a ray from the camera position to the vertex
    Out.t0 = vEyePos.xyz - vPos.xyz;

    // Compute the position in clip space
    Out.Position = mul(vPos, mWorldViewProj);

    // Compute final Rayleigh and Mie colors
    Out.c0.xyz = cFrontColor * (vInvWavelength.xyz * krESun);
    Out.c1.xyz = cFrontColor * kmESun;

    // Pass the light direction vector along to the pixel shader
    Out.LightDirection = vLightDir;

    return Out;
}

PSOut
AtmosphereFromSpacePS(AtmosphereVSOut In)
{
    PSOut Out;

    float cos = saturate(dot (In.LightDirection, In.t0) / length (In.t0));
    float cos2 = cos*cos;

    float fMiePhase = getMiePhase(cos,cos2,g,g2);
    float fRayleighPhase = getRayleighPhase(cos2);

    float exposure = 2.0;
    Out.color.rgb = 1.0 - exp(-exposure * (fRayleighPhase * In.c0 + fMiePhase * In.c1));
    Out.color.a = Out.color.b;

    return Out;
    }

এটি এখনও কাজ করে কিনা আমাকে জানান। আপনার যদি অন্য কোনও সহায়তার দরকার হয় তবে আমি আমার কোডটি খনন করার চেষ্টা করব। আমি মনে করি রেন্ডারিং করতে আমি দুটি ক্ষেত্র ব্যবহার করেছি: একটি পৃষ্ঠের জন্য এবং একটি বায়ুমণ্ডলের জন্য।


0

কিছু চিন্তার ট্র্যাক: আপনার ফ্লোটের যথার্থতা পরীক্ষা করুন। মহাকাশ স্কেলে, বেশিরভাগ সময় ফ্লোট 32 যথেষ্ট নয়। আপনার বিক্ষিপ্ত শেডারের নীচে গোলকের মতো আদিম উপস্থাপনা থাকলে ডিপিথ বাফারটি পরীক্ষা করুন।

এই নিদর্শনগুলি, রাইট্র্যাকিংয়ের পাশাপাশি পাওয়া যায়, এগুলি সাধারণত ভাসমান নির্ভুলতার সমস্যাগুলি থেকে প্রাথমিক পৃষ্ঠের সাথে প্রাথমিক স্তরের সাথে গৌণ রশ্মি ছেদ করা হয়।

সম্পাদনা করুন: 1000 এ (সমস্ত ইন্টিজারগুলি 16 বিগ বিস্তৃত ম্যান্টিসার জন্য 16% ফ্লোট 32 প্রতিনিধিত্ব পর্যন্ত সম্পূর্ণরূপে নিন্দনীয়), একটি ফ্লোট 32 এর পরবর্তী নম্বরটি 1000.00006103 তাই আপনার যথার্থতা এখনও এই পরিসীমাটিতে বেশ ভাল pretty

তবে আপনি যদি মিটার রেঞ্জ ব্যবহার করতে চান তবে কোনও গ্রহকে এই দূরত্বটি দেখতে 100,000,000,000 এর মান হবে এবং পরেরটি 100000008: 8,000 মিটার নির্ভুলতার 100,000km এ হবে।

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

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

তিনি এই ধরণের ব্যাপ্তিতে গভীরতা বাফার সমস্যার কথাও উল্লেখ করেছেন এবং লোগারিদমিক জেড স্কেলগুলি প্রবর্তন করার জন্য এটি প্রথম একজন, যদি প্রথম না হয় তবে একজন। http://www.gamedev.net/blog/73/entry-2006307-tip-of-the-day-logarithmic-zbuffer-artifacts-fix/ এখানে আরও অনেক সম্পূর্ণ: http://outerra.blogspot.jp/ 2012/11 / পূর্ণবিস্তার গভীর বাফার পরিসরের-and.html

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


আপনি কি ভাসমান নির্ভুলতার দ্বারা বোঝাতে চাইছেন? উদাহরণস্বরূপ ব্যবহৃত হচ্ছে যে স্কেলগুলি -1000 থেকে 1000 এর উদাহরণ The উদাহরণটি এই মুহূর্তে একটি সফ্টওয়্যার বাস্তবায়ন, যেখানে শেডারের ফলাফলটি একটি চিত্রকে রেন্ডার করা হয় এবং তারপরে সি # সিস্টেম.ড্রেইং এপিআই ব্যবহার করে প্রদর্শিত হয়, যা মানে উদাহরণটি আদিম ব্যবহার করে না।
অলিপেক্কা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.