2011-12-13 16 views
11

Tôi đang tạo một trò chơi trong OpenGL nơi tôi có một vài đối tượng trong không gian thế giới. Tôi muốn thực hiện một chức năng mà tôi có thể lấy vị trí của đối tượng (3D) và biến nó thành vị trí của màn hình (2D) và trả về nó.C++/OpenGL chuyển đổi coords thế giới thành màn hình (2D) coords

Tôi biết các vị trí 3D của đối tượng, ma trận bảo vệ và xem ma trận trong varibles sau:

Matrix projectionMatrix; 
Matrix viewMatrix; 
Vector3 point3D; 

Trả lời

29

Để làm điều này biến đổi, trước tiên bạn phải mất vị trí mô hình không gian của bạn và chuyển đổi chúng để cắt -không gian. Điều này được thực hiện với nhân ma trận. Tôi sẽ sử dụng mã GLSL kiểu để làm cho nó rõ ràng những gì tôi đang làm:

vec4 clipSpacePos = projectionMatrix * (viewMatrix * vec4(point3D, 1.0)); 

Chú ý làm thế nào tôi chuyển đổi vector 3D của bạn thành một vector 4D trước khi nhân. Điều này là cần thiết bởi vì ma trận là 4x4, và bạn không thể nhân một ma trận 4x4 với một vector 3D. Bạn cần một thành phần thứ tư.

Bước tiếp theo là chuyển đổi vị trí này từ không gian clip thành không gian tọa độ thiết bị chuẩn hóa (không gian NDC). Không gian NDC nằm trên phạm vi [-1, 1] trong cả ba trục. Này được thực hiện bằng cách chia ba tọa độ đầu tiên do thứ tư:

vec3 ndcSpacePos = clipSpacePos.xyz/clipSpacePos.w; 

Rõ ràng, nếu clipSpacePos.w là zero, bạn gặp rắc rối, vì vậy bạn nên kiểm tra trước. Nếu nó bằng không, thì điều đó có nghĩa là vật thể nằm trong mặt phẳng chiếu; đó là chiều sâu không gian xem là bằng không. Và các đỉnh như vậy được tự động cắt bớt bởi OpenGL.

Bước tiếp theo là chuyển đổi từ không gian [-1, 1] này sang tọa độ tương đối cửa sổ. Điều này yêu cầu sử dụng các giá trị bạn đã chuyển đến glViewport. Hai thông số đầu tiên là độ lệch từ phía dưới bên trái của cửa sổ (vec2 viewOffset) và hai thông số thứ hai là chiều rộng/chiều cao của khu vực khung nhìn (vec2 viewSize). Với các vị trí này, vị trí không gian cửa sổ là:

vec2 windowSpacePos = ((ndcSpacePos.xy + 1.0)/2.0) * viewSize + viewOffset; 

Và đó là như bạn đi. Hãy nhớ rằng: không gian cửa sổ của OpenGL có liên quan đến dưới cùng bên trái của cửa sổ, không phải ở trên cùng bên trái.

+0

Tôi làm cách nào để đạt được điều này mà không cần sử dụng chương trình đổ bóng? Tôi có nghĩa là, chỉ cần các chức năng OpenGL đơn giản? – mr5

+0

Câu trả lời hay nhất tôi đã tìm thấy sau khi Googling một thời gian và chỉ có một tôi đã tìm thấy rằng đề cập đến phải chia cho clipSpacePos.w. –

+2

Lưu ý: nếu không gian cửa sổ nếu liên quan đến phía trên bên trái của cửa sổ, thì 'windowSpacePos' phải là ' vec2 (((ndcSpacePos.x + 1.0)/2.0) * viewSize.x + viewOffset.x, ((1.0 - ndcSpacePos.y)/2.0) * viewSize.y + viewOffset.y) ' –

Các vấn đề liên quan