Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.
Posted 28 May 2002 - 09:29 AM
-- <-- Sun at top of trapezoid
/ \
/ \
------ <-- Ground at bottom of trapezoid
Posted 28 May 2002 - 02:49 PM
quote:
greeneggs wrote:
This is the basic simple idea. I imagine getting the shafts and the colors just right requires playing around a little. (For example, if there are no clouds crossing the sun, then you probably don''t want any visible shafts, so set the 1-d texture to have alpha = 0 everywhere.)
quote:
kill wrote:
How should the sun be blended with the clouds? I can''t come up with a way of doing it that''s really pleasing to the eye.
quote:
kill wrote:
I just came back from Lake George (I went there for the Memorial Day weekend). The scenery there is beautiful, however I couldn''t fully enjoy it because I kept looking at the clouds, landscape, vegetation and water and kept trying to point out all the different effects I should implement. Ignorance is truly bliss. My non-programming friends enjoyed everything so much more then I did
Posted 28 May 2002 - 03:33 PM
quote:
Original post by kill
I just came back from Lake George (I went there for the Memorial Day weekend). The scenery there is beautiful, however I couldn''t fully enjoy it because I kept looking at the clouds, landscape, vegetation and water and kept trying to point out all the different effects I should implement. Ignorance is truly bliss. My non-programming friends enjoyed everything so much more then I did
Posted 29 May 2002 - 07:45 AM
Posted 29 May 2002 - 11:52 AM
Posted 30 May 2002 - 10:11 AM
/*
* convection.c
*
*/
#include "convection.h"
#include <stdlib.h>
#include <math.h> // for exp
#include <stdio.h>
typedef int bool;
#define true 1
#define false 0
static float *vx, *vy, *vz, *vxnew, *vynew, *vznew;
static float *E, *Enew;
static float *wv, *wl, *wvnew, *wlnew;
static float deltaT = 0;
static float vaporSource = 0;
void convectionVelocity(float **vxh, float **vyh, float **vzh) { *vxh = vx; *vyh = vy; *vzh = vz; }
float *convectionTemperature() { return E; }
float convectionDeltaT() { return deltaT; }
float *convectionVapor() { return wv; }
float *convectionDroplets() { return wl; }
float convectionVaporSource() { return vaporSource; }
#define array(a,x,y,z) a[((z)+1)*(wy+2)*(wx+2) + ((y)+1)*(wx+2) + (x)+1]
#define cleararray(a) for (z = -1; z < wz+1; z++) for (y = -1; y < wy+1; y++) for (x = -1; x < wx+1; x++) a(x,y,z) = 0;
#define swaparray(a,b) temp = a; a = b; b = temp;
#define addperiodic(a) \
for (z = -1; z < wz+1; z++) {
for (x = -1; x < wx+1; x++) {
a(x,wy-1,z) += a(x,-1,z); a(x,-1,z) = a(x,wy-1,z);
a(x, 0,z) += a(x,wy,z); a(x,wy,z) = a(x, 0,z);
}
for (y = -1; y < wy+1; y++) {
a(wx-1,y,z) += a(-1,y,z); a(-1,y,z) = a(wx-1,y,z);
a( 0,y,z) += a(wx,y,z); a(wx,y,z) = a( 0,y,z);
}
}
#define copyperiodic(a) \
for (z = -1; z < wz+1; z++)
for (x = -1; x < wx+1; x++) { a(x,-1,z) = a(x,wy-1,z); a(x,wy,z) = a(x,0,z);
for (y = -1; y < wy+1; y++) { a(-1,y,z) = a(wx-1,y,z); a(wx,y,z) = a(0,y,z);
}
#define addreflections(a) \
for (x = -1; x < wx+1; x++) for (y = -1; y < wy+1; y++) { a(x,y,1) += a(x,y,-1); a(x,y,wz-2) += a(x,y,wz); }
#define swapreflections(a) \
for (x = -1; x < wx+1; x++) for (y = -1; y < wy+1; y++) { a(x,y,1) -= a(x,y,-1); a(x,y,wz-2) -= a(x,y,wz); }
#define clearreflections(a) \
for (x = -1; x < wx+1; x++) for (y = -1; y < wy+1; y++) { a(x,y,0) = 0; a(x,y,wz-1) = 0; }
#define vx(x,y,z) array( vx,x,y,z)
#define vy(x,y,z) array( vy,x,y,z)
#define vz(x,y,z) array( vz,x,y,z)
#define vxnew(x,y,z) array(vxnew,x,y,z)
#define vynew(x,y,z) array(vynew,x,y,z)
#define vznew(x,y,z) array(vznew,x,y,z)
static bool velocityInitialized = false;
static void initializeVelocity(float vamp) {
int x, y, z;
if (velocityInitialized) return;
vx = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
vy = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
vz = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
cleararray(vx)
cleararray(vy)
cleararray(vz)
// small amplitude random initial velocities
for (z = 0; z < wz; z++) {
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
vx(x,y,z) = vamp * (rand() / (float) RAND_MAX - 0.5f);
vy(x,y,z) = vamp * (rand() / (float) RAND_MAX - 0.5f);
vz(x,y,z) = vamp * (rand() / (float) RAND_MAX - 0.5f);
}
}
}
copyperiodic(vx)
copyperiodic(vy)
copyperiodic(vz)
clearreflections(vz)
vxnew = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
vynew = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
vznew = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
cleararray(vxnew)
cleararray(vynew)
cleararray(vznew)
clearreflections(vz)
velocityInitialized = true;
}
#define E(x,y,z) array(E,x,y,z)
#define Enew(x,y,z) array(Enew,x,y,z)
static bool temperatureInitialized = false;
static void initializeTemperature(float dT) {
int x, y, z;
if (temperatureInitialized) return;
deltaT = dT;
E = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
cleararray(E)
// small amplitude random initial temperatures
for (z = 1; z < wz-1; z++) {
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
E(x,y,z) = deltaT * (rand() / (float) RAND_MAX - 0.5f);
}
}
}
// top and bottom plates are separated by fixed temperature differential 2 deltaT
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
E(x,y, 0) = deltaT;
E(x,y,wz-1) = -deltaT;
}
}
copyperiodic(E)
Enew = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
cleararray(Enew)
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
Enew(x,y, 0) = deltaT;
Enew(x,y,wz-1) = -deltaT;
}
}
copyperiodic(Enew)
temperatureInitialized = true;
}
#define wv(x,y,z) array( wv,x,y,z)
#define wl(x,y,z) array( wl,x,y,z)
#define wvnew(x,y,z) array(wvnew,x,y,z)
#define wlnew(x,y,z) array(wlnew,x,y,z)
static bool vaporInitialized = false;
static void initializeVapor(float vs) {
int x, y, z;
if (vaporInitialized) return;
vaporSource = vs;
wv = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
wl = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
cleararray(wv)
cleararray(wl)
// top and bottom plates are separated by fixed vapor differential vaporSource
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
wv(x,y, 0) = vaporSource;
wv(x,y,wz-1) = 0;
}
}
copyperiodic(wv)
copyperiodic(wl)
wvnew = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
wlnew = (float *) malloc((wx+2) * (wy+2) * (wz+2) * sizeof(float));
cleararray(wvnew)
cleararray(wlnew)
copyperiodic(wvnew)
copyperiodic(wlnew)
vaporInitialized = true;
}
static bool convectionInitialized = false;
void initializeConvection() {
if (convectionInitialized) return;
initializeVelocity(1.0f);
initializeTemperature(.04f); //.01f for stable pattern // 1.8 * lambda + .3 for onset of oscillation?
initializeVapor(5.75f);
convectionInitialized = true;
}
#define delta(arr,x,y,z) \
(.1666666666667f * (arr(x-1,y,z)+arr(x+1,y,z)+arr(x,y-1,z)+arr(x,y+1,z)+arr(x,y,z-1)+arr(x,y,z+1)) - arr(x,y,z))
// should the second constant be .125f? check
#define graddivvx(x,y,z) \
(.5f * (vx(x+1,y,z)+vx(x-1,y,z)) - vx(x,y,z) + f * \
(vy(x+1,y+1,z)-vy(x+1,y-1,z)-vy(x-1,y+1,z)+vy(x-1,y-1,z)+vz(x+1,y,z+1)-vz(x+1,y,z-1)-vz(x-1,y,z+1)+vz(x-1,y,z-1)))
#define graddivvy(x,y,z) \
(.5f * (vy(x,y+1,z)+vy(x,y-1,z)) - vy(x,y,z) +5f * \
(vx(x+1,y+1,z)-vx(x-1,y+1,z)-vx(x+1,y-1,z)+vx(x-1,y-1,z)+vz(x,y+1,z+1)-vz(x,y+1,z-1)-vz(x,y-1,z+1)+vz(x,y-1,z-1)))
#define graddivvz(x,y,z) \
(.5f * (vz(x,y,z+1)+vz(x,y,z-1)) - vz(x,y,z) 25f * \
(vx(x+1,y,z+1)-vx(x-1,y,z+1)-vx(x+1,y,z-1)+vx(x-1,y,z-1)+vy(x,y+1,z+1)-vy(x,y-1,z+1)-vy(x,y+1,z-1)+vy(x,y-1,z-1)))
void convectionTimestep(float dt) {
int x, y, z;
int l, m, n;
float dx, dy, dz;
float *temp;
if (!convectionInitialized) initializeConvection();
// Eulerian part
{ // (a) buoyancy procedure
float kb = 3E0f; // not specified in [Yanagita & Kaneko 95], 5 or 6 seems to be what they use, though
for (z = 0; z < wz; z++) { // 0, wz for fixed; 1, wz-1 for reflective boundary
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
vznew(x,y,z) = vz(x,y,z) + kb * ( E(x,y,z) - .25f*(E(x+1,y,z)+E(x-1,y,z)+E(x,y+1,z)+E(x,y-1,z)) );
}
}
}
swaparray(vz,vznew)
copyperiodic(vz)
}
{ // (b) heat diffusion
float kdE = .2f; // .4f, .02f
for (z = 1; z < wz-1; z++) { // 1, wz-1 always
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
Enew(x,y,z) = E(x,y,z) + kdE * delta(E,x,y,z);
}
}
}
swaparray(E,Enew)
copyperiodic(E)
}
{ // vapor diffusion -- do water droplets diffuse?
float kdw = 1E-1f; // .4f, .02f
for (z = 1; z < wz-1; z++) { // 1, wz-1 always
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
wvnew(x,y,z) = wv(x,y,z) + kdw * delta(wv,x,y,z);
wlnew(x,y,z) = wl(x,y,z) + kdw * delta(wl,x,y,z);
}
}
}
swaparray(wv,wvnew)
//swaparray(wl,wlnew)
copyperiodic(wv)
//copyperiodic(wl)
}
{ // © viscosity and pressure effect
float kv = .2f;
float kp = .2f;
for (z = 0; z < wz; z++) { // 1, wz-1 for reflection
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
vxnew(x,y,z) = vx(x,y,z) + kv * delta(vx,x,y,z)
+ kp * graddivvx(x,y,z);
vynew(x,y,z) = vy(x,y,z) + kv * delta(vy,x,y,z)
+ kp * graddivvy(x,y,z);
vznew(x,y,z) = vz(x,y,z) + kv * delta(vz,x,y,z)
+ kp * graddivvz(x,y,z);
}
}
}
swaparray(vx,vxnew)
swaparray(vy,vynew)
swaparray(vz,vznew)
copyperiodic(vx)
copyperiodic(vy)
copyperiodic(vz)
}
// Lagrangian part
#define advect(a,b) \
b( l, m, n) += (1-dx)*(1-dy)*(1-dz) * ,y,z); \
b(l+1, m, n) += dx *(1-dy)*(1-dz) * ,y,z); \
b( l,m+1, n) += (1-dx)* dy *(1-dz) * ,y,z); \
b(l+1,m+1, n) += dx * dy *(1-dz) * ,y,z); \
b( l, m,n+1) += (1-dx)*(1-dy)* dz * ,y,z); \
b(l+1, m,n+1) += dx *(1-dy)* dz * ,y,z); \
b( l,m+1,n+1) += (1-dx)* dy * dz * ,y,z); \
b(l+1,m+1,n+1) += dx * dy * dz * a(x,y,z);
{
cleararray(vxnew)
cleararray(vynew)
cleararray(vznew)
cleararray(Enew)
cleararray(wlnew)
cleararray(wvnew)
for (z = 1; z < wz-1; z++) { // 0, wz
for (y = 0; y < wy; y++) {
for (x = 0; x < wx; x++) {
dz = z + vz(x,y,z);
if (dz < 0) dz = -dz; //continue; // for fixed boundary, just continue
if (dz >= wz-1) dz = (float) (2*(wz-1)-z);//continue;
dy = y + vy(x,y,z);
if (dy < 0) dy += wy;
if (dy >= wy) dy -= wy;
dx = x + vx(x,y,z);
if (dx < 0) dx += wx;
if (dx >= wx) dx -= wx;
l = (int) dx; dx -= l;
m = (int) dy; dy -= m;
n = (int) dz; dz -= n;
advect(vx,vxnew)
advect(vy,vynew)
advect(vz,vznew)
advect(E,Enew)
advect(wl,wlnew)
advect(wv,wvnew)
}
}
}
swaparray(vx,vxnew)
swaparray(vy,vynew)
swaparray(vz,vznew)
swaparray(E,Enew)
swaparray(wl,wlnew)
swaparray(wv,wvnew)
addperiodic(vx)
addperiodic(vy)
addperiodic(vz)
addperiodic(E)
addperiodic(wl)
addperiodic(wv)
addreflections(vx)
addreflections(vy)
swapreflections(vz)
addreflections(E)
//clearreflections(vx)
//clearreflections(vy)
clearreflections(vz)
addreflections(wv)
addreflections(wl)
}
for (y = -1; y < wy+1; y++) {
for (x = -1; x < wx+1; x++) {
E(x,y, 0) = deltaT;
E(x,y,wz-1) = -deltaT;
wv(x,y, 0) = vaporSource;
//wv(x,y,wz-1) = 0;
wl(x,y,0) = 0;
//wl(x,y,wz-1) = 0;
}
}
{ // phase transition
float alpha = 1E-2f;
float Q = 7E-4f; // cal / g??
#define altitude 6000.0f
#define wmax(T) (217 * (float) exp(19.482f - 4303.4f / ((T) - 29.5f)) / (T))
float wmax = .5f;//300 - 0.6f * altitude / 100.0f;
float delta;
//float temperature;
for (z = 0; z < wz; z++) {
//temperature = 300 - 0.6f * (altitude + 20 * z) / 100.0f; // for cumulus clouds only
//wmax = wmax(temperature);
for (y = 0; y < wy; y++) {
x = 0;
//printf("%d %d %d %4.1f %4.5f %4.5f %4.5f %4.2f\t", x,y,z,E(x,y,z),wmax,delta,wv(x,y,z),wl(x,y,z));
for (x = 0; x < wy; x++) {
wmax = wmax(264+E(x,y,z));
delta = wv(x,y,z) - wmax;
//if (x == wy/2)
//printf("%d %d %d %4.1f %4.5f %4.5f %4.5f %4.2f\t\n", x,y,z,E(x,y,z),wmax,delta,wv(x,y,z),wl(x,y,z));
//printf("%d %d %d %4.1f %4.5f %4.5f %4.5f %4.2f\t", x,y,z,E(x,y,z),wmax,delta,wv(x,y,z),wl(x,y,z));
if (delta > 0) {
wvnew(x,y,z) = wv(x,y,z) - alpha * delta;
wlnew(x,y,z) = wl(x,y,z) + alpha * delta;
} else {
if (wl(x,y,z) + alpha * delta < 0) delta = -wl(x,y,z);
wvnew(x,y,z) = wv(x,y,z) - alpha * delta;
wlnew(x,y,z) = wl(x,y,z) + alpha * delta;
}
Enew(x,y,z) = E(x,y,z) - Q * delta;
}
}
}
swaparray(wv,wvnew)
swaparray(wl,wlnew)
swaparray(E,Enew)
copyperiodic(wv)
copyperiodic(wl)
copyperiodic(E)
}
{ // restore boundary conditions
for (y = -1; y < wy+1; y++) {
for (x = -1; x < wx+1; x++) {
E(x,y, 0) = deltaT;
E(x,y,wz-1) = -deltaT;
wv(x,y, 0) = vaporSource;
//wv(x,y,wz-1) = 0;
wl(x,y,0) = 0;
//wl(x,y,wz-1) = 0;
}
}
{ // try setting a horizontal flow as a boundary condition? (as in [Miyazaki, Yoshida, Dobashi & Nishita])
for (y = -1; y < wy+1; y++) {
for (x = -1; x < wx+1; x++) {
#define tempscale 1.25f
vx(x,y, 0) = .125f * tempscale;
vx(x,y,wz-1) = -.01625f * tempscale;
vy(x,y, 0) = .01625f * tempscale;
vy(x,y,wz-1) = .125f * tempscale;
//vz(x,y, 0) = .25f;
//vz(x,y,wz-1) = -.125f;
}
}
}
}
}
Posted 31 May 2002 - 04:30 AM
quote:
Without any ray-tracing for rendering, though, I don't see how one can expect good results. For example, consider noontime when (assume) the sun is directly overhead. The shading ray-tracer is tracing through parallel vertical lines, and so is trivial (it just takes the value from the heightfield). A typical cloud will be dark in the middle, with a lighter stripe around the outside, since this is what the height field looks like. However, even clouds near the horizon will look like this, foreshortened in perspective. And this is incorrect.
quote:
I think that you are not actually shading at high resolution, but are using the heightfield, exponentiated, to give the additional detail? This isn't really physically accurate but if it works who am I to argue?
quote:
In "A method for modeling clouds based on atmospheric fluid dynamics" (Miyazaki, Yoshida, Dobashi & Nishita), they show some results on making 2-dimensional Benard convection cells for cirrocumulus clouds. Has anyone gotten this running in real-time? (I imagine the three dimensional computations are too slow, although clouds change slowly so maybe it's doable.) These are very impressive results, much better than their cloud automata models.
Posted 31 May 2002 - 06:09 AM
Posted 01 June 2002 - 12:35 AM
Posted 01 June 2002 - 02:52 AM
Posted 01 June 2002 - 07:44 AM
Posted 03 June 2002 - 04:41 PM
Posted 06 June 2002 - 04:10 AM
Posted 06 June 2002 - 07:54 AM
Posted 06 June 2002 - 08:51 AM
Posted 06 June 2002 - 10:41 AM
quote:
So how do you animate the cloud Yann? Do you just animate the Perlin Noise and thats it? Can you just (linearly) interpolate 2 Noises together, or maybe more? How can you simulate this scenario: It starts out a bright sunny day, later it gets cloudy, and finally at dusk all hell breaks loose with violent clouds (I won''t mention the lighting :-).
quote:
How do you shoot rays through the 2D Plane. You mentioned voxels. So you break up the noise texture as a plane (when it is in 3D Space) into a bunch of Axis Aligned Bounding Boxes or something similar maybe?
quote:
This step really stumps me. And you do this to simulate scattering, right?
quote:
Would this be an Isotropic or Anisotropic process?
quote:
Also, maybe off topic. Have you sen any of the research using particles to simulate clouds with billboard impostors (and VFC) as performance enhancements. It creates realistic 3D volumetric clouds and they look amazing, but for a game with a ground perspective, seems a bit useless. But is it really? Have you done any research into performance wayoff''s? For something that looks better, do you think it is too expensive or would the perlin noise calculations compare?
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.
GameDev.net™, the GameDev.net logo, and GDNet™ are trademarks of GameDev.net, LLC.