3d数学:屏幕空间到世界空间 [英] 3d Math : screen space to world space

查看:178
本文介绍了3d数学:屏幕空间到世界空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在过去的6个小时中,我一直在尝试在我的webgl应用中实现点击,但是我找不到关于此主题的足够清晰的信息.

I've been trying to implement clicking in my webgl app for the last 6 hours and I can't find anything clear enough about this subject.

到目前为止,我想出的是伪代码:

What I have came up with so far is, in pseudo code:

screenSpace = mousePosition;
normalizedScreenSpace = (screenSpace.x/screen.width, screenSpace.y/screen.height);

camSpace = invertProjectionMatrix * normalizedScreenSpace;

worldSpace = invertViewMatrix * camSpace;

打印出worldSpace坐标,它不对应于场景中的其他对象.我在做什么错了?

Printing out the worldSpace coordinates, and it doesn't corresponds to other objects in the scene. What am I doing wrong?

推荐答案

viewProjection矩阵将vec3从世界空间带到剪贴空间,因此它的逆函数将反向空间剪贴到世界空间.唯一缺少的是gpu在引擎盖后面为您处理的视角鸿沟,因此您也必须考虑到这一点.添加屏幕的宽度和高度,即可将屏幕显示到世界各地:

The viewProjection matrix brings a vec3 from world space to clip space and so its inverse does the reverse, clip space to world space. Whats missing is the perspective divide that gpu handles for you behind the hood so you have to account for that as well. Add in the screen width and height and you have your screen to world:

screenToWorld: function(invViewProjection, screenWidth, screenHeight){
    // expects this[2] (z value) to be -1 if want position at zNear and +1 at zFar

    var x = 2*this[0]/screenWidth - 1.0;
    var y = 1.0 - (2*this[1]/screenHeight); // note: Y axis oriented top -> down in screen space
    var z = this[2];
    this.setXYZ(x,y,z);
    this.applyMat4(invViewProjection);
    var m = invViewProjection;
    var w = m[3] * x + m[7] * y + m[11] * z + m[15]; // required for perspective divide
    if (w !== 0){
        var invW = 1.0/w;
        this[0] *= invW;
        this[1] *= invW;
        this[2] *= invW;
    }

    return this;
},

和相反的计算:

worldToScreen: function(viewProjectionMatrix, screenWidth, screenHeight){
    var m = viewProjectionMatrix;
    var w = m[3] * this[0] + m[7] * this[1] + m[11] * this[2] + m[15]; // required for perspective divide
    this.applyMat4(viewProjectionMatrix);
    if (w!==0){ // do perspective divide and NDC -> screen conversion
        var invW = 1.0/w;
        this[0] = (this[0]*invW + 1) / 2 * screenWidth;
        this[1] = (1-this[1]*invW) / 2 * screenHeight; // screen space Y goes from top to bottom
        this[2] *= invW;
    } 
    return this;
},

这篇关于3d数学:屏幕空间到世界空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆