Calculate ray direction vector from screen coordan

2019-08-26 01:59发布

问题:

I'm looking for a better way (or a note that this is the best way) to transfer a pixel coordinate to its corresponding ray direction from a arbitrary camera position/direction.

My current method is as follows. I define a "camera" as a position vector, lookat vector, and up vector, named as such. (Note that the lookat vector is a unit vector in the direction the camera is facing, NOT where (position - lookat) is the direction, as is the standard in XNA's Matrix.CreateLookAt) These three vectors can uniquely define a camera position. Here's the actual code (well, not really the actual, a simplified abstracted version) (Language is HLSL)

float xPixelCoordShifted = (xPixelCoord / screenWidth * 2 - 1) * aspectRatio;
float yPixelCoordShifted = yPixelCoord / screenHeight * 2 - 1;
float3 right = cross(lookat, up);
float3 actualUp = cross(right, lookat);
float3 rightShift = mul(right, xPixelCoordShifted);
float3 upShift = mul(actualUp, yPixelCoordShifted);
return normalize(lookat + rightShift + upShift);

(the return value is the direction of the ray)

So what I'm asking is this- What's a better way to do this, maybe using matrices, etc. The problem with this method is that if you have too wide a viewing angle, the edges of the screen get sort of "radially stretched".

回答1:

You can calculate it (ray) in pixel shader, HLSL code:

float4x4 WorldViewProjMatrix; // World*View*Proj
float4x4 WorldViewProjMatrixInv; // (World*View*Proj)^(-1)

void VS( float4 vPos : POSITION,
     out float4 oPos : POSITION,
     out float4 pos  : TEXCOORD0 )
{
    oPos = mul(vPos, WorldViewProjMatrix);
    pos = oPos;
}

float4 PS( float4 pos : TEXCOORD0 )
{
    float4 posWS = mul(pos, WorldViewProjMatrixInv);
    float3 ray = posWS.xyz / posWS.w;

    return float4(0, 0, 0, 1);
}

The information about your camera's position and direction is in View matrix (Matrix.CreateLookAt).