Really great results guys! I wish I could achieve at least something relatively close to what you have for my game.
That GPU 7 Pro article mostly describes ways to create a realistic clouds in terms of density functions and overall weather simulation, but it somehow assumes that reader is already familiar with ray marching techniques. While I can understand the algorithm behind a single ray cast from a given point to sample various density functions and so on, I can't get my head over the more basic stuff like - what render pass does it all happen? Is it during rendering the skybox? Or do you render some special shape and then in it's shader you do all this? What does it mean to do raycasts in this cast? Is it per pixel? Per point in a world space? They say in the article they assume some spherical shell around the camera of some thickness, but how do you pick points on that sphere for actual raycast? And how is the result from such raycast used to actually shade the sky?
Are there some papers on basics like this? If you could provide some pseudocode used to actually "draw" and execute this shader that's supposed to create clouds, including what are you rendering, and what's the input for raymarching algorithm, it would greatly help me understand this concept.
it's a post-process render pass, so you just render a quad.
first you get a ray accord to the screen pixel's coordinate, calculate the intersect point of the camera ray and the bottom cloud sphere.
the intersect point is the start point, run step along the ray.
float Raymarcher::integrate(const V3f& pos, const V3f& dir, const float absorption) const
{
// Determine intersection with the buffer
float t0, t1;
if (false == m_buffer->intersect(pos, dir, t0, t1))
return 1.0f;
// Calculate number of integration steps
const int numsteps = int(ceil(t1 - t0) / m_stepsize);
// Calculate step size
const float ds = (t1 - t0) / numsteps;
V3d stepdir(dir);
stepdir *= ds;
V3d raypos(pos);
raypos += stepdir;
const float rhomult = -absorption * ds;
// Transmittance
float T = 1.f;
for (int step = 0; step < numsteps; ++step) {
float rho = m_buffer.trilinearInterpolation(raypos);
T *= std::exp(rhomult * rho);
if (T < 1e-8)
break;
raypos += stepdir;
}
return T;
}
this code is from siggraph 2011 course Production Volume Rendering, you should read it.