- 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)