- Home /
 
Skyboxes, GetPixel and Raycast Directions
Hi there,
I'm currently making a raytraced renderer using recursive Raycasts and up till now, I have just been using the color black for a trace, that doesn't collide with anything.
So I was wondering how you reproduce unity's display of skyboxes, by just having a Vector3 direction and the skybox material.
Thank you, Benproductions1
If any more information is needed, just ask :)
Answer by Wolfram · Feb 01, 2013 at 02:51 PM
This is not tested, but I'd do it like this:
First you need to figure out which of your 6 skybox textures to sample. This is determined by the dominant axis of your direction:
 if(Mathf.Abs(dir.x)>Mathf.Abs(dir.y)){
     if(Mathf.Abs(dir.x)>Mathf.Abs(dir.z)){
         // x is dominant axis.
         if(dir.x<0){
             // -X is dominant axis -> left face
         }else{
             // +X is dominant axis -> right face
         }
     }else{
         // z is dominant axis.
         ... // similar
     }
 }else if(Mathf.Abs(dir.y)>Mathf.Abs(dir.z)){
     // y is dominant axis.
     ... // similar
 }else{
     // z is dominant axis.
     ... // similar
 }
 
               If it's a cubemap, then you supply your dominant axis to the GetPixel() call. Otherwise, get your textures from the shader (mat.GetTexture("_FrontTex") etc.)
Once you have the face, you need to figure out which WC axes correspond to which texture axes. For example, if -X is your dominant direction, you "look" along -X, so +Y points up and +Z points right. Therefore +Z corresponds to texture.u, and -Y corresponds to texture.v (texture origin is always upper left).
Then you need to compute the orthogonal normalized texture coordinates. Start with a normalized [-1..1] space:
 texture.u=dir.z/(-dir.x); // for the -X example
 texture.v=-dir.y/(-dir.x); // for the -X example
 
               You will now need to transform this to [0..1] space:
 texture.u=(texture.u+1)/2;
 texture.v=(texture.v+1)/2;
 
               And finally to [0..texture.width|height] space:
 texture.u*=texture.width;
 texture.v*=texture.height;
 
               These are your pixel coordinates, which you can feed to GetPixel().
Additional notes:
for Texture2D you can use GetPixelBilinear() to find interpolated pixel colors, AFAIK you can only point-sample Cubemaps at integer coordinates.
you will need to take care of correct orientation for the up/down textures, the axes might be rotated by 180 degrees or something.
Thank you! $$anonymous$$aking RayTracing is quite difficult :) Even though it might not explicitly work, it's definitely the right direction I'll come back once it's implemented and accept your answer
So I made a quick implementation, and I am definitely drawing the skybox per pixel, but with the wrong texture coords... return (skybox.GetTexture("_LeftTex") as Texture2D).GetPixelBilinear(direction.z/-direction.x, direction.y/-direction.x); Is the calculation I'm doing for the Left texture, similarly with the others. Did I understand your method wrong?
It seems you missed a "-" for the y-coordinate, but otherwise it should work.
For the other faces you'll have to flip axes around. For example, (-Z/X,-Y/X) for +X, (-X/-Z,-Y/-Z) for -Z, (X/Y,Z/Y) for +Y, and so on.
It seems as though me missing the $$anonymous$$us was correct... Adding in the "+1)/2" fixes it completely, giving the desired result...
 return (skybox.GetTexture("_LeftTex") as Texture2D).GetPixelBilinear((direction.z/-direction.x+1)/2, (direction.y/-direction.x+1)/2);
 
                  Thank you very much :)
For future reference, the axis flips are as follows: -X(-Z, +Y), +X(+Z, +Y), -Z(+X, +Y), +Z(-X, +Y), -Y(-X, Z), +Y(-X, -Z)
Your answer