# Correct ray calculation

I am using compute shader to raycast a scene. I already had a camera model but it is distorted in the ends - that’s why I wanted to use the monogame lookat and projection matrices for raycasting.

I found this site: How to create correct ray tracing camera. – bmrysz.wordpress.com

but it doesnt turn out right yet.

I create my conventional view and projection matrix (that works correctly for rendering mesh-models) like so:

``````// ViewMatrix:
var cameraRotation = Matrix.CreateRotationX(_pitch) * Matrix.CreateRotationY(_yaw);
var transformedForward = Vector3.Transform(Vector3.Forward, cameraRotation);
var direction = CameraPosition + transformedForward;

Matrices["View"] = Matrix.CreateLookAt(CameraPosition, direction, Vector3.Up);

// ProjectionMatrix:
Matrices["Projection"] = Matrix.CreatePerspectiveFieldOfView(
FieldOfView,
0.1f,
1000.0f);

//Inverse:
Matrices["InverseViewProj"] = Matrix.Invert(Matrix.Multiply(Matrices["View"], Matrices["Projection"]));

``````

It works just fine for models but when I use these matrices inside my compute shader the rays are not calculated correctly:

``````float2 screenCoordinate = float2((float) globalId.x * OneOverScreenWidth, (float) globalId.y * OneOverScreenHeight); // (what this basically does is map the globalId that ranges from 0 to Width/Height of rendertarget to 0 to 1.

float2 uv = (screenCoordinate * 2.0f) - float2(1, 1);

Ray ray = (Ray) 0;

float4 screenSpaceFar = float4(uv, 1.0f, 0.0f);
float4 screenSpaceNear = float4(uv, 0.0f, 0.0f);

float4 far = mul(ViewProjectionInverse, screenSpaceFar); // changing order doesnt change the outcome
far /= far.w;
float4 near = mul(ViewProjectionInverse, screenSpaceNear);
near /= near.w;

ray.Origin = CameraPosition;
ray.Dir = normalize(far.xyz - near.xyz);
ray.DirReciprocal = rcp(ray.Dir);
``````

Basically it’s very similar to ViewPort.Unproject but it doesnt turn out right:

How can I create rays that exactly corresponds with the perspective of mesh-rendering?

Thank God, i found the solution: what was required were the homogenous coordinates meaning:

``````float2 screenCoordinate = float2((float) globalId.x * ScreenWidth, (float) globalId.y * ScreenHeight);
float2 uv = (screenCoordinate * 2.0f) - float2(1, 1);

Ray ray = (Ray) 0;

float4 screenSpaceFar = float4(float2(uv.x, -uv.y), 1.0f, 1.0f);
float4 screenSpaceNear = float4(float2(uv.x, -uv.y), 0.0f, 1.0f);

float4 far = mul(screenSpaceFar, ViewProjectionInverse);
far /= far.w;
float4 near = mul(screenSpaceNear, ViewProjectionInverse);
near /= near.w;

ray.Origin = CameraPosition;
ray.Dir = normalize(far.xyz - near.xyz);
ray.DirReciprocal = rcp(ray.Dir);
``````

Now it works fine:

1 Like