I added a sky to my raytracer that gets sampled when a ray completely misses any object.


What I'm doing here is if a ray completely misses anything in the scene, it returns the Perlin noise function at (ray.direction.x, ray.direction.y, ray.direction.z) - in other words it "samples a sphere around the origin".

But it "looks wrong" (because the sky looks like it's facing you).

How can I improve the sky and make it look more like the earth's horizon?

Or is this more or less what it should look like, and I should simply add more geometry on the floor?

  • \$\begingroup\$ I agree it looks distinctly unnatural. BTW how is you camera going to work? Do you need a full skybox or just a backdrop and do you want to generate the sky using noise or is sampling from a texture fine? If its just a backdrop (ala a 2.5D game) you could sample from something like this images.bibliocad.com/library/image/00010000/9000/… which would be tileable is its a panoramic. \$\endgroup\$ – ClassicThunder Feb 11 '12 at 4:28
  • 2
    \$\begingroup\$ Some kind of transformation to the Y coordinate (or Z, if that's your "upwards" coordinate) might do something. For example, y' = 1 − (1 − y)^2. The idea being to compress the Y coordinate around y = 0, and keep it the same or expand it near y = 1. \$\endgroup\$ – John Calsbeek Feb 11 '12 at 5:12
  • \$\begingroup\$ @Calsbeek this would be a great answer! :) \$\endgroup\$ – Maik Semder Feb 11 '12 at 10:21

Alternatively you could use a cube map with a sky texture instead of using perlin noise. And I also think that will make your scene look better due to having more detail and variation in the environment mapping. That's exactly what I did when I implemented my raytracer.

Another reason I recommend this, is that the environment does not need to be only clouds. It can have mountains, it can be an indoor scene, can be a scene from mars. Using a cube map the only thing you need to do is swap the texture and you're done.

So the first step will be to find a cube map that fits your needs. It could be stored as six separate textures, or as a single texture like the one below. Also check this link for more info on how to create your own:

enter image description here

Then on your code, I'd recommend creating a CubeMap class to encapsulate the sampling calculations. This class should know how to load the cube map texture, and given a ray it should be able to know in which face and in what position to sample. In my implementation I found it easier to store each of the six faces in separate texture objects, and branch based on the direction of the ray:

class CubeMap
    public void Load(string path);
    public Color GetSample(Ray ray);
    private Texture[6] faces;

In case you don't have a Texture class yet, just create your own. It can be as simple as a two dimensional array of colors. So, just as a reference, and with no guarantee on the efficiency or soundness of this implementation, here's the code I used on my project - CubeMap and CubeFace.

| improve this answer | |
  • \$\begingroup\$ This answer skirts the issue - I want to know how to make the texture I generated appear as the earth's sky dome. \$\endgroup\$ – bobobobo Jun 5 '12 at 19:14

You might try using 2D Perlin with (ray.dir.x/ray.dir.z, ray.dir.y/ray.dir.z). The projects the direction vector onto the Z=1 plane. It should give you the effect of an infinite (flat) sky.

| improve this answer | |

You might want to check Iñigo Quilez's (iq) Dynamic Clouds article out -- It looks like something that might fit your ticket.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.