Jump to content


WebGL SkyGen Tool

webgl

10 replies to this topic

#1 TheNut

    Senior Member

  • Moderators
  • 1719 posts
  • LocationCyberspace

Posted 06 June 2012 - 08:52 PM

The other day I was thinking how I wanted some skyboxes for my next WebGL demo I'm working on. I found a couple online and then the geek syndrome started to kick in. I thought how much more interesting it would be to try and craft my own skyboxes similar to Terragen. I already had some code to do atmospheric scattering and perlin noise for clouds, so I just combined the two and came up with this WebGL tool. It is no where near as sophisticated as the type of rendering algorithms used by Terragen (= god in digital form), but it was a fun tool to make and I think it's good enough to use for simple games. In fact, one interesting side-effect of using low resolution clouds is that they look very suitable for cartoon or cel-shaded based games.

The demo is available here. The UI is pretty basic. Just play around with the sliders to see what does what :D

Here is a sample skybox rendered at dusk.

Posted Image


You can also export the texture on each cube face if you want higher resolution. The following two images demonstrate the skybox used in another demo.

Posted Image

Posted Image
http://www.nutty.ca - Being a nut has its advantages.

#2 Reedbeta

    DevMaster Staff

  • Administrators
  • 5344 posts
  • LocationSanta Clara, CA

Posted 06 June 2012 - 09:48 PM

Nice! Only quibble I have is that the Mie sliders seem to make it difficult to get the sun to be a realistic size (small) without removing it entirely. But the sky color sure works nicely. I assume this is all physically based scattering simulation? Any HDR / tonemapping?
reedbeta.com - developer blog, OpenGL demos, and other projects

#3 TheNut

    Senior Member

  • Moderators
  • 1719 posts
  • LocationCyberspace

Posted 07 June 2012 - 01:19 AM

Yeah, the sliders are finicky because of the high range they cover. You can get precise control by selecting the slider and using the arrow keys to shift the value in small increments. Setting the mie scatter constant (second slider from the Rayleigh / Mie group) to 0.0003 will produce a small sun. You can further drop it to 0.001 at the horizon where the scattering effect is greatest, causing the sun to blowout.

The scattering algorithm is based off Sean O'Neil's implementation described in GPU Gems, which uses Nishita's rayleigh scattering formula published in '93. I made a few adjustments to get the algorithm to run completely in the fragment shader as a raytracer, which produces much better results at the expense of speed. It's worth it IMO.

I don't use HDR, despite that I would love to. I just don't like the fact that floating point textures are only available as an extension in WebGL. I loath the idea that some could run it while others may not. I may implement it as a bonus feature if the support is available, we'll see. I'd also have to implement an EXR exporter for people (myself!) that would want to maintain the HDR data.
http://www.nutty.ca - Being a nut has its advantages.

#4 Reedbeta

    DevMaster Staff

  • Administrators
  • 5344 posts
  • LocationSanta Clara, CA

Posted 07 June 2012 - 04:58 AM

Ahh, I didn't realize floating-point textures might not be available in WebGL. Although, the whole thing is in one shader, correct? So you could perform HDR calculations and tone-mapping all in there, though you wouldn't be able to save the floating-point data.

I actually prefer the Radiance .hdr format for HDR images. It's a bit arcane to read/write properly, but can be done in a couple hundred lines of code you can add to a project, vs that monstrosity that is the OpenEXR SDK. :)

Actually, I bet you could encode the Radiance RGBE format in a pixel shader and save it out to a regular 8-bit texture. Prepend a header and save it, and you're done!
reedbeta.com - developer blog, OpenGL demos, and other projects

#5 TheNut

    Senior Member

  • Moderators
  • 1719 posts
  • LocationCyberspace

Posted 07 June 2012 - 11:21 AM

True, I could perform the HDR inside the shader as it is all self contained. It's more about the HDR export for me, but I didn't think about the RGBE format. I'll have to try that out. Only a few lines of code too, woot!
http://www.nutty.ca - Being a nut has its advantages.

#6 TheNut

    Senior Member

  • Moderators
  • 1719 posts
  • LocationCyberspace

Posted 07 June 2012 - 09:39 PM

Well I didn't have much success with these encoding formats. I've tried both RGBE and LogLuv, both of which exhibit numerous problems.

Posted Image

The first problem in my implementation is that both RGBE and LogLuv display thin bright rings at certain edges along the bands (which is another problem). The problem appears related to linear filtering, since disabling that fixes the issue. I'm not exactly sure why that is an issue since logically both formats encode data in a way that is filter friendly. The encodings also appear to be destructive, as you can see in the image the surface of the sun appears altered, more so in the LogLuv implementation. The banding is definitely an issue with RGBE. Larson even admits that it's a potential problem due. LogLuv does a fairly decent job at reducing the bands, but it suffers more from discs appearing in the image. You can kind of make out the disk in the image, but it's more prevalent when you increase the exposure.

To be on the safe side, I assumed I misinterpreted Larson's paper or his algorithm. So I tried a couple other implementations I found scoured on the Internet. I found an optimized version of the LogLuv formula here. Interestingly, this version does not suffer from the rings I was getting due to linear filtering, but it suffers horribly with banding and discs, far more than my "true to the paper" implementation. At some points it looks like you're staring down a discrete multicoloured tube.

Posted Image

Now I have tried the algorithm on standard gradient images and they do appear fine, so I'm wondering if perhaps atmospheric scattering falls under the exception to the rule. Perhaps the dynamic range requirements are stretching the capabilities possible with just 32 bits? I don't know, but I'm losing faith here :D
http://www.nutty.ca - Being a nut has its advantages.

#7 Reedbeta

    DevMaster Staff

  • Administrators
  • 5344 posts
  • LocationSanta Clara, CA

Posted 07 June 2012 - 10:52 PM

I've definitely gotten banding due to bilinear filtering with RGBM - haven't tried it with RGBE or LogLuv, but I'd expect that there'd be similar issues. They're only filtering-friendly in a very approximate way; high-contrast areas will still cause problems.

I'm surprised that the RGBE still didn't work well even with filtering turned off, though; we've used it (in the form of .hdr files) and haven't encountered too many issues. Although, it does have problems with highly saturated colors sometimes.
reedbeta.com - developer blog, OpenGL demos, and other projects

#8 fireside

    Senior Member

  • Members
  • PipPipPipPip
  • 1620 posts

Posted 08 June 2012 - 12:37 AM

Pretty nice. Might try it in Unity when I get a little further with my "taking forever" game.
Currently using Blender and Unity.

#9 Stainless

    Member

  • Members
  • PipPipPipPip
  • 610 posts
  • LocationSouthampton

Posted 08 June 2012 - 10:11 AM

A few years ago I did a similar thing, I'll try and find the source code for the app.

Mine was a little different as it was designed to create sky spheres for all planet types.

You passed in atmospheric contents, star type, and the planets physical properties and location, then let it churn.

I shelved it a long time ago because I couldn't get rid of banding in some circumstances ( and work took over the time I was spending on it :( )

I would love to see the techniques you are using and compare them with mine.

#10 TheNut

    Senior Member

  • Moderators
  • 1719 posts
  • LocationCyberspace

Posted 08 June 2012 - 12:54 PM

Reed, both algorithms work well when filtering is disabled. LogLuv just does a slightly better job at removing the banding issue. I haven't implemented a filtering algo in the shader yet. I'm going to take the algo offline and run a couple hundred HDR images through it to see what comes out and whether or not it can meet my [exorbant] expectations before I continue with it.

Fireside, I think the name "forever" has been trademarked by Apogee. You might have to settle for "till death do us part" or some such :D

Stainless, banding is indeed annoying. It's a pity 48bpp devices haven't mainstreamed yet, but hopefully before I retire :) The base of my technique is derived from this article. The main difference is I pushed everything to the fragment shader and I fixed up the code so I could support both ground based and space based renders. It would be nice to develop the backend to calculate the optimized density scaling to support different planetary configurations, but O'Neil's default values are sufficient for the time being. A good site with relatively up-to-date information on atmospheric rendering is also available here. I based my cloud rendering on this article (cloud cover and haze only), with the exception I didn't bother with his lighting model because it was gimmicky. I'd like to do mie scattering with clouds, but the paper I got on that will take some time to absorb. It deals more with volumetric cloud rendering, which for the time being I don't care for.
http://www.nutty.ca - Being a nut has its advantages.

#11 Stainless

    Member

  • Members
  • PipPipPipPip
  • 610 posts
  • LocationSouthampton

Posted 11 June 2012 - 09:50 AM

I went out and bought a copy of "cloud dynamics" http://books.google....0-hertz&f=false

Cost me £57.00 :(

However it just goes into too much detail about things I really didn't care about, and not enough about the things I am interested in. The maths is a bit of a nightmare as well, I guess that's why weather forecasts are all wrong.

I'll dig my backup out and put the code somewhere, you might be able to steal some of it, or just compare and contrast.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users