Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

okonomiyaki

My sky screenshot! One last step- shading

This topic is 5684 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am very proud to present the following sky in my game: There is actually a dome gradient but I didn''t turn it on for that screenshot. I haven''t gotten the gradient looking very good yet (realistic colors, etc) so I decided I liked that violet color without gradient for now. The fact is my clouds are done. Except for one thing: shading. They may look shaded but it''s actually kind of random modulating with Perlin Noise alpha values. What is the EASIEST and QUICKEST technique to shade clouds? I''ve heard of some kind of scattering techniques before but I looked up some papers but I wanted to know if that''s the way to go. I''m pretty content with my sky right now but I''d like to add a little shading that considers the direction of the sun. If there''s no quick way to do that, maybe I''ll just have to leave that off for next project. And since I''m looking for an easy way I know that it won''t look the best. I would also like any comments on my sky. It is semi-dynamic, in that it moves around but I haven''t really gotten "transforming" clouds in that new clouds are generated on the fly with noise. But I''m content now and this is my first project so I want to move on to the actual logic of the program. What do you think? Anything you think I should do more to it? Critique!

Share this post


Link to post
Share on other sites
Advertisement
The correct sky gradient is very easy to calculate, and there is another thread in this forum with description and screenshots. Maybe you can search for it using google?

Here is some code off my hard drive. It looks more complicated than it is, since there is some code to find the sun''s exact position based on date, time and position on the Earth. Also, there''s some junk dealing with scaling, saturation, gamma-correction, displaying the sun. This makes very realistic sky gradients, except for overcast days, night (of course).


float PerezFunction(
float coeffs[5];
float theta, gamma;
float thetaS, lvz;
)
{
float A = coeffs[0], B = coeffs[1], C = coeffs[2], D = coeffs[3], E = coeffs[4];

float den = (1 + A * exp(B)) * (1 + C * exp(D * thetaS) + E * cos(thetaS)*cos(thetaS));
float num = (1 + A * exp(B / cos(theta))) * (1 + C * exp(D * gamma) + E * cos(gamma)*cos(gamma));
return (lvz * num / den);
}

float AngleBetween(float thetav, phiv, theta, phi) {
float cospsi = sin(thetav) * sin(theta) * cos(phi-phiv) + cos(thetav) * cos(theta);
if (cospsi > 1) return 0;
if (cospsi < -1) return PI;
return acos(cospsi);
}

void sunPosition(
float timeOfDay, julianDay, latitude;
float standardMeridian, longitude;
output float thetaS, phiS;
)
{
float solarTime, solarDeclination, solarAltitude, opp, adj, solarAzimuth;

solarTime = timeOfDay +
(0.170 * sin(4 * PI * (julianDay - 80) / 373) - 0.129 * sin(2 * PI * (julianDay - 8) / 355)) +
(standardMeridian - longitude) / 15;
solarDeclination = (0.4093 * sin(2 * PI * (julianDay - 81) / 368));
solarAltitude = asin(sin(radians(latitude)) * sin(solarDeclination) -
cos(radians(latitude)) * cos(solarDeclination) * cos(PI * solarTime / 12));

opp = -cos(solarDeclination) * sin(PI * solarTime / 12);
adj = -(cos(radians(latitude)) * sin(solarDeclination) +
sin(radians(latitude)) * cos(solarDeclination) * cos(PI * solarTime / 12));
solarAzimuth = atan(opp, adj);

phiS = -solarAzimuth;
thetaS = PI / 2 - solarAltitude;
}

surface
skycolor (
float timedSun = 1;

vector toSun = (1, -2, 1.5);

float timeOfDay = 12, julianDay = 180, latitude = 37;
float standardMeridian = 0, longitude = 0;

float turb = 3;

float sphericalProjection = 0;
float exposureControl = 1;
float showSun = 0;

float linearScale = 25;//50;//50//25 for T=2.5
float exponentialScale = 25;//45;//45//10
)
{
toSun = normalize(toSun);
uniform float thetaS = acos(zcomp(toSun));
uniform float phiS = atan(ycomp(toSun), xcomp(toSun));
if (timedSun == 1) {
sunPosition(timeOfDay, julianDay, latitude, standardMeridian, longitude, thetaS, phiS);
}
toSun = (sin(thetaS) * cos(phiS), sin(thetaS) * sin(phiS), cos(thetaS));

uniform float theta2, theta3, T, T2, chi, zenith_Y, zenith_x, zenith_y;
uniform float perez_Y[5], perez_x[5], perez_y[5];

theta2 = thetaS * thetaS;
theta3 = theta2 * thetaS;
T = turb;
T2 = turb * turb;

chi = (4 / 9 - T / 120) * (PI - 2 * thetaS);
zenith_Y = (4.0453 * T - 4.9710) * tan(chi) - .2155 * T + 2.4192;
//zenith_Y *= 1000; // conversion from kcd/m^2 to cd/m^2

zenith_x =
( 0.00165 * theta3 - 0.00375 * theta2 + 0.00209 * thetaS + 0.0) * T2 +
(-0.02903 * theta3 + 0.06377 * theta2 - 0.03202 * thetaS + 0.00394) * T +
( 0.11693 * theta3 - 0.21196 * theta2 + 0.06052 * thetaS + 0.25886);

zenith_y =
( 0.00275 * theta3 - 0.00610 * theta2 + 0.00317 * thetaS + 0.0) * T2 +
(-0.04214 * theta3 + 0.08970 * theta2 - 0.04153 * thetaS + 0.00516) * T +
( 0.15346 * theta3 - 0.26756 * theta2 + 0.06670 * thetaS + 0.26688);

perez_Y[0] = 0.17872 * T - 1.46303;
perez_Y[1] = -0.35540 * T + 0.42749;
perez_Y[2] = -0.02266 * T + 5.32505;
perez_Y[3] = 0.12064 * T - 2.57705;
perez_Y[4] = -0.06696 * T + 0.37027;

perez_x[0] = -0.01925 * T - 0.25922;
perez_x[1] = -0.06651 * T + 0.00081;
perez_x[2] = -0.00041 * T + 0.21247;
perez_x[3] = -0.06409 * T - 0.89887;
perez_x[4] = -0.00325 * T + 0.04517;

perez_y[0] = -0.01669 * T - 0.26078;
perez_y[1] = -0.09495 * T + 0.00921;
perez_y[2] = -0.00792 * T + 0.21023;
perez_y[3] = -0.04405 * T - 1.65369;
perez_y[4] = -0.01092 * T + 0.05291;


// shader code starts here

color skycolor = 0;

vector Iw = normalize(transform("world", I));
float theta = acos(zcomp(Iw));
float phi = atan(ycomp(Iw), xcomp(Iw));

if (sphericalProjection == 1) {
vector Indc = transform("NDC", I);
phi = atan(xcomp(Indc) - .5, ycomp(Indc) - .5);
theta = asin(2 * length((xcomp(Indc) - .5, ycomp(Indc) - .5, 0)));
}

float gamma = AngleBetween(theta, phi, thetaS, phiS);
// Compute xyY values
float x = PerezFunction(perez_x, theta, gamma, thetaS, zenith_x);
float y = PerezFunction(perez_y, theta, gamma, thetaS, zenith_y);
float Y = PerezFunction(perez_Y, theta, gamma, thetaS, zenith_Y);

float X = (x / y) * Y;
float Z = ((1 - x - y) / y) * Y;

float R = 3.240479 * X - 1.537150 * Y - 0.498535 * Z;
float G = -0.969256 * X + 1.875992 * Y + 0.041556 * Z;
float B = 0.055648 * X - 0.204043 * Y + 1.057311 * Z;


if (exposureControl == 1) {
/*skycolor = color (
1-exp(-(1/exponentialScale) * R),
1-exp(-(1/exponentialScale) * G),
1-exp(-(1/exponentialScale) * B)
);*/
float max, min, delta, hue, saturation, value;
max = max(R, G, B);
min = min(R, G, B);
value = max;
saturation = (value != 0) ? ((max - min) / max) : 0;
if (saturation == 0) hue = 0; // undefined
else {
delta = max - min;
if (R == max) hue = (G - B) / delta;
else if (G == max) hue = 2 + (B - R) / delta;
else if (B == max) hue = 4 + (R - G) / delta;
hue *= 60;
if (hue < 0) hue += 360;
hue /= 360;
}
value = 1 - exp(-(1/exponentialScale) * value);
//value /= linearScale;
skycolor = color "hsv" (hue, saturation, value);
} else {
//skycolor = color (R, G, B) / linearScale;
float max, min, delta, hue, saturation, value;
max = max(R, G, B);
min = min(R, G, B);
value = max;
saturation = (value != 0) ? ((max - min) / max) : 0;
if (saturation == 0) hue = 0; // undefined
else {
delta = max - min;
if (R == max) hue = (G - B) / delta;
else if (G == max) hue = 2 + (B - R) / delta;
else if (B == max) hue = 4 + (R - G) / delta;
hue *= 60;
if (hue < 0) hue += 360;
hue /= 360;
}
//value = 1 - exp(-(1/exponentialScale) * value);
value /= linearScale;
skycolor = color "hsv" (hue, saturation, value);
}

// gamma correction
#define gamma 2.5
skycolor = color (pow(comp(skycolor,0),1/gamma),pow(comp(skycolor,1),1/gamma),pow(comp(skycolor,2),1/gamma));

if (sphericalProjection == 0 && zcomp(Iw) < 0) skycolor = 0;

Oi = 1;
Ci = skycolor;

if (showSun == 1) {
if (sphericalProjection == 0) {
Ci = mix(Ci, color(1,0,0), pow(Iw . toSun, 256));
} else {
vector Indc = transform("NDC", I);
setzcomp(Indc, 0);
float Sradius = .5 * sin(thetaS);
vector Sndc = (sin(phiS) * Sradius + .5, cos(phiS) * Sradius + .5, 0);
if (length(Sndc - Indc) < .01) Ci = color (1, 0, 0);
}
}
}


Share this post


Link to post
Share on other sites
Yes, I have seen that sky thread many times But I had lost the link to it so thank you very much for reminding me of it.

greeneggs: Thanks a bunch for your code. I'm looking through it and I like some of the concepts behind it. I won't use it exactly but I will implement something similar, thanks for the ideas. I have a basic gradient down it just doesn't account for the sun and doesn't look very realistic.
And thanks samith

[edited by - okonomiyaki on January 23, 2003 1:31:36 AM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!