Horizon:zero Dawn Cloud System

Started by
78 comments, last by IlPresidente 5 years, 8 months ago

Hi all,

I'm new here, I'm a CS student with this new fabolous hobby! I decided to sign in this community after I was stuck with my version of HZD clouds since I saw the source of WFP, who I thank. 
This is what I achieved so far: 

Spoiler

unknown.png

 

Spoiler

unknown.png?width=911&height=535

There's still room of improvement of course (e.g. HG phase function is not implemented, but for now I have a question: I want to merge this work in a Procedural Terrain that I already have ready, (a pic in spoiler)

Spoiler

gitpic.jpg

but i don't know well how to do it. At the moment (as you can see) the clouds are rendered inside a cube. The terrain is made by squared tiles. Do you think is better switch from a cube to the "canonical" two concentric sphere or let stay the cube model? 

 

Thank you all for your help!

 

PS: Thank to Andrew Schneider for his beautiful work!

Advertisement

A sphere shape would give you better results, as it produces a "natural" horizon. Should be pretty easy to do if you're doing the clouds as a fullscreen effect and writing it out to an FBO. Inside the shader just trace from the eye to a sphere, centered below your terrain, so you only get a small upper part. The intersection is your trace start.
Just be aware that the height inside the cloud is then no longer along the global up axis but the height above the traced sphere in direction towards the spere-center.

For performance optimization, early out in the shader if a ray is way below the horizon.
Another thing i suggest is doing sphere/shell like sampling, means from the trace start point on you sample in shells not in height slices. That (for me at least) reduced sampling errors and still looks good when you're inside the cloud layer. Also it makes exponential sampling distances easier.

11 hours ago, Ryokeen said:

A sphere shape would give you better results, as it produces a "natural" horizon. Should be pretty easy to do if you're doing the clouds as a fullscreen effect and writing it out to an FBO. Inside the shader just trace from the eye to a sphere, centered below your terrain, so you only get a small upper part. The intersection is your trace start.
Just be aware that the height inside the cloud is then no longer along the global up axis but the height above the traced sphere in direction towards the spere-center.

For performance optimization, early out in the shader if a ray is way below the horizon.
Another thing i suggest is doing sphere/shell like sampling, means from the trace start point on you sample in shells not in height slices. That (for me at least) reduced sampling errors and still looks good when you're inside the cloud layer. Also it makes exponential sampling distances easier.

Honestly I tried with sphere shape but i had some problem with picking the right uv. Anyway, do you have any advice about the lighting/coloring of the clouds? ATM i followed the algorithm of WFP but it produces to me effects like dark border. Also, I didn't understood well between which vectors the HG phase function must be calculated.

For the volume texture lookup just use worldspace/whatever space you want to use in which the sampling ray is. For the clouddensity texture, the 2D one, just use the sampling x/y coordinate with some shift and scaling. As my world is 0,0,0 centered i center that 2D texture on that point aswell and scale it so it covers the visible area.

The HG phase function uses the view direction and the light direction. Had to play a bit with them, so i end up with 3 HG phase functions. One for the forward part, one for backwars and one for ambient, with different g values. Not sure about the dark borders you mention, but if they are at the cloud edges, where they are only partly visible, that might be some blending error. Try using premultiplied alpha for that.

Also there is some Frostbite paper about improving the scattering equations https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/s2016_pbs_frostbite_sky_clouds.pdf

1 hour ago, Ryokeen said:

For the volume texture lookup just use worldspace/whatever space you want to use in which the sampling ray is. For the clouddensity texture, the 2D one, just use the sampling x/y coordinate with some shift and scaling. As my world is 0,0,0 centered i center that 2D texture on that point aswell and scale it so it covers the visible area.

 The HG phase function uses the view direction and the light direction. Had to play a bit with them, so i end up with 3 HG phase functions. One for the forward part, one for backwars and one for ambient, with different g values. Not sure about the dark borders you mention, but if they are at the cloud edges, where they are only partly visible, that might be some blending error. Try using premultiplied alpha for that.

Also there is some Frostbite paper about improving the scattering equations https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/s2016_pbs_frostbite_sky_clouds.pdf

View direction meaning SamplingPoint-EyePosition? 
For dark edges I mean this: 

Spoiler

 

DvxZRVC.png


 

I blend with the background doing (in glsl) 


vec4 finalColor = vec4(mix(background.rgb, cloud_color.rgb, cloud.a), 1.0);

I think (perhaps incorrectly) is due to the color integration ( src.col *= src.a; ) in the raymarcher... 

The sampling itself looks a bit odd, like stretched towards the screen center. And yes view direction is samplingpoint-EyePosition, but as you move along a ray direction that is the same, so no need to recalculate it.

For the dark edges, it looks a bit like the cloud gets brigther the thicker it is.

What i do for composition


vec3 color = CloudColor.rgb + CloudColor.a*background.rgb;

While doing the raymarch i assume you go front to back, so start with extinction = 1.0, inScatter(cloud color) = 0.0
for each step


sigT = cloudDensityAtSamplePoint * someValue;//some value is just a scaling to account for the step lenght, overall density..	
curExt = exp( -sigT);		
curInScatter = ..compute lighting for that samplepoint
inScatter = inScatter + sigT * curInScatter * extinction;//compute new overall inScatter amount
extinction *= curExt;//compute new overall extinction

vec4 finalCloudColor = vec4(inScatter*LightColor,extinction);

 

3 hours ago, Ryokeen said:

The sampling itself looks a bit odd, like stretched towards the screen center. And yes view direction is samplingpoint-EyePosition, but as you move along a ray direction that is the same, so no need to recalculate it.

For the dark edges, it looks a bit like the cloud gets brigther the thicker it is.

What i do for composition



vec3 color = CloudColor.rgb + CloudColor.a*background.rgb;

While doing the raymarch i assume you go front to back, so start with extinction = 1.0, inScatter(cloud color) = 0.0
for each step



sigT = cloudDensityAtSamplePoint * someValue;//some value is just a scaling to account for the step lenght, overall density..	
curExt = exp( -sigT);		
curInScatter = ..compute lighting for that samplepoint
inScatter = inScatter + sigT * curInScatter * extinction;//compute new overall inScatter amount
extinction *= curExt;//compute new overall extinction

vec4 finalCloudColor = vec4(inScatter*LightColor,extinction);

 

So the view direction is the... ray direction? Because I tried to calculate the dot between LightDir and ViewDir but it didn't seemed to work, about the phase function, even lerping with two differents g coefficient.

Are you sure the composition formula is right? if the alphaness of a cloud color is about 1.0 it'll result like white... 

I'll try this code too, thank you. At worst, i'll post my code too. It's quite a clone to the one posted by WFP 2 page ago.

Yep, just be aware to normalize the directions before taking the dot product


float LdotE = dot(vLightDirection,vRay); //both normalized, vRay is from Eye towards the clouds, vLightDirection is towards light
float MainPhase = GetMainPhase(LdotE); //combination of HG-phase functions

I could post my code aswell, but it's a mess atm and written in CgFx..yeah shame on me had no time to port it over to glsl yet

I think I kind of solved:

WSpLLrp.jpg

There is still no scattering modeling and no spherical model. Also, I dropped the Powder effect. For the raymarching, I used an approach similar to tailorswift's one.

 

About the optimization, I've a question about OpenGL/GLSL: does the using of texturelod affects (in positive) the performance?

This topic is closed to new replies.

Advertisement