আমি এই কাগজের উপর ভিত্তি করে আকাশের রঙ গণনা করার জন্য একটি অ্যালগরিদম প্রয়োগ করার চেষ্টা করছি (পেরেজের মডেল)। আমি শেডার প্রোগ্রামিং শুরু করার আগে আমি গণিতের ধারণাটি পরীক্ষা করতে চেয়েছিলাম। ইতিমধ্যে কিছু সমস্যা আছে আমি মুক্তি পেতে পারি না। হয়তো কেউ ইতিমধ্যে অ্যালগরিদম বাস্তবায়ন করেছে।
আমি নিখুঁত জেনিটাল আলোকসজ্জার সমীকরণ দিয়ে শুরু করেছি Yz
, xz
এবং yz
কাগজে প্রস্তাবিত (পৃষ্ঠা 22)। মানগুলি Yz
যুক্তিসঙ্গত বলে মনে হয়। নীচের চিত্রটি 5 টি Yz
টারবডিটির জন্য সূর্যের জেনিটাল দূরত্বের ফাংশন হিসাবে দেখায় T
:
ফাংশন গামা (জেনিথ, আজিমুথ, সোলারজিনিথ, সোলারাজিমুথ) প্রদত্ত জেনিটাল দূরত্ব এবং প্রদত্ত অবস্থানে আজিমুথ এবং সূর্যের সাথে একটি বিন্দুর মধ্যে কোণ গণনা করে। এই ফাংশনটিও কার্যকর বলে মনে হচ্ছে। নিম্নলিখিত চিত্রটি এই কোণটি solarzenith=0.5
এবং এর জন্য দেখায় solarazimuth=0
। zenith
উপরে থেকে নীচে (0 থেকে পাই / 2) azimuth
বৃদ্ধি পায়, বাম থেকে ডানে বৃদ্ধি পায় (পি থেকে পাই পর্যন্ত) আপনি সূর্যের অবস্থানটি পরিষ্কার দেখতে পাচ্ছেন (উজ্জ্বল স্পট, কোণটি শূন্য হয়ে যায়):
পেরেজ ফাংশন (এফ) এবং সহগগুলি কাগজে দেওয়া হিসাবে প্রয়োগ করা হয়েছে। তারপরে রঙের মানগুলি YYY হওয়া উচিত absolute value * F(z, gamma) / F(0, solarzenith)
। আমি আশা করি সেই মানগুলি [0,1] এর মধ্যে হবে। তবে এটি ওয়াই উপাদানটির ক্ষেত্রে নয় (বিশদগুলির জন্য নীচে আপডেট দেখুন)। এখানে কিছু নমুনা মান রয়েছে:
{Y, x, y}
{19.1548, 0.25984, 0.270379}
{10.1932, 0.248629, 0.267739]
{20.0393, 0.268119, 0.280024}
এখানে বর্তমান ফলাফল:
সমস্ত গণনা সহ গণিত নোটবুক এখানে এবং পিডিএফ সংস্করণ পাওয়া যাবে ।
কাগজের মতো একই ফলাফল পেতে আমার কী পরিবর্তন করতে হবে এমন ধারণা কি কারও আছে?
কোড মত সি
// this function returns the zenital Y component for
// a given solar zenital distance z and turbidity T
float Yz(float z, float T)
{
return (4.0453 * T - 4.9710)*tan( (4.0f/9-T/120)*(Pi-2*z) ) - 0.2155 * T + 2.4192
}
// returns zenital x component
float xz(float z, float T)
{
return //matrix calculation, see paper
}
// returns zenital y component
float yz(float z, float T)
{
return //matrix calculation, see paper
}
// returns the rgb color of a Yxy color
Color RGB(float Y, float x, float y)
{
Matrix m; //this is a CIE XYZ -> RGB conversion matrix
Vector v;
v.x = x/y*Y;
v.y = Y;
v.z = (1-x-y)/y*Y;
v = M * v; //matrix-vector multiplication;
return Color ( v.x, v.y, v.z );
}
// returns the 5 coefficients (A-E) for the given turbidity T
float[5] CoeffY(float T)
{
float[5] result;
result[0] = 0.1787 * T - 1.4630;
result[1] = -0.3554 * T + 0.4275;
...
return result;
}
//same for Coeffx and Coeffy
// returns the angle between an observed point and the sun
float PerezGamma(float zenith, float azimuth, float solarzenith, float solarazimuth)
{
return acos(sin(solarzenith)*sin(zenith)*cos(azimuth-solarazimuth)+cos(solarzenith)*cos(zenith));
}
// evalutes Perez' function F
// the last parameter is a function
float Perez(float zenith, float gamma, float T, t->float[5] coeffs)
{
return (1+coeffs(T)[0] * exp(coeffs(T)[1]/cos(zenith)) *
(1+coeffs(T)[2] * exp(coeffs(T)[3]*gamma) +
coeffs(T)[4]*pow(cos(gamma),2))
}
// calculates the color for a given point
YxyColor calculateColor(float zenith, float azimuth, float solarzenith, float solarazimuth, float T)
{
YxyColor c;
float gamma = PerezGamma(zenith, azimuth, solarzenith, solarazimuth);
c.Y = Yz(solarzenith, T) * Perez(zenith, gamma, T, CoeffY) / Perez(0, solarzenith, T, CoeffY);
c.x = xz(solarzenith, T) * Perez(zenith, gamma, T, Coeffx) / Perez(0, solarzenith, T, Coeffx);
c.y = yz(solarzenith, T) * Perez(zenith, gamma, T, Coeffy) / Perez(0, solarzenith, T, Coeffy);
return c;
}
// draws an image of the sky
void DrawImage()
{
for(float z from 0 to Pi/2) //zenithal distance
{
for(float a from -Pi to Pi) //azimuth
{
YxyColor c = calculateColor(zenith, azimuth, 1, 0, 5);
Color rgb = RGB(c.Y, c.x, c.y);
setNextColor(rgb);
}
newline();
}
}
সমাধান
প্রতিশ্রুতি হিসাবে আমি আকাশ রেন্ডারিং সম্পর্কে একটি ব্লগ নিবন্ধ লিখেছিলাম। আপনি এটি এখানে খুঁজে পেতে পারেন ।