gpt4 book ai didi

c++ - 从固定功能迁移到 GLSL OpenGL : How should I modify my view (lookAt) matrix and perspection matrix?

转载 作者:行者123 更新时间:2023-11-28 04:39:23 31 4
gpt4 key购买 nike

我正在尝试将我的 OpenGL 渲染管道从定点迁移到现代 OpenGL。我的定点 3D 管道多年来一直运行良好。现在,当我切换到 GLSL 时,最终的投影和对象方向看起来像“完全镜像或交换”。我已经排除了所有其他原因(比如未能设置矩阵制服等),因为我可以通过随机拖动鼠标平移相机来不时看到 3D 场景渲染。因此,问题缩小为以下内容:

  • 生成 View 矩阵的函数(我的函数getViewMat(pos, lookat, upaxis))
  • 生成透视投影矩阵的函数(我的函数getPerspectiveMat(fov, aspect, nearZ, farZ))

由于这两个函数之前为定点管线生成了正确的 View /投影矩阵,现在我想知道是否/如何修改它们以使生成的矩阵适用于着色器管线?

很少stack overflow threads建议对于着色器管道,我们需要手动翻转投影矩阵的 Z 值,但是 View 矩阵呢?非常感谢您的任何建议。

更新:源代码

/*
Matrix4f has class members "float m00, m01, m02, m03, m10, m11, ..., m33" representing
a row-dominant 4x4 matrix, when passed to GLSL, I have remembered to transpose them
*/
void Matrix4f::_getPerspectiveByFov(float fov, float aspectRatio, float nearZ, float farZ, int matrixType)
{
float halfFov = MathUtil::degToRad(fov) * 0.5f;
float width, height;
//We use the small side out of width and height as the base size, then calculate the other side by aspect ratio.
float _tanFOV = (float)tan(halfFov);
if(aspectRatio < 1.f)//width is smaller
{
width = 2.f * nearZ * _tanFOV;
height = width / aspectRatio;
}
else //height is smaller
{
height = 2.f * nearZ * _tanFOV;
width = height * aspectRatio;
}

/*
Formula from OpenGL reference, see function "glFrustum".
|w 0 0 0|
|0 h 0 0|
|0 0 -C D|
|0 0 1 0|

w = 2.f * nearZ / width
h = 2.f * nearZ / height
C = -(farZ + nearZ) / (farZ - nearZ)
D = -2.f * farZ * nearZ / (farZ - nearZ);
*/
float w = 2.f * nearZ / width; // Is equal to: [ 1.f / tan(fov*0.5f) ]
float h = 2.f * nearZ / height; // Is equal to: [ 1.f / tan(fov*0.5f) / aspectRatio ]
float C = -(farZ + nearZ) / (farZ - nearZ);
float D = -2.f * farZ * nearZ / (farZ - nearZ);

//-----------------------
m00 = w;
m01 = 0.f;
m02 = 0.f;
m03 = 0.f;

m10 = 0.f;
m11 = h;
m12 = 0.f;
m13 = 0.f;

m20 = 0.f;
m21 = 0.f;
m22 = -C;
m23 = D;

m30 = 0.f;
m31 = 0.f;
m32 = 1.f;
m33 = 0.f;
}

void Matrix4f::_getLookAt(Vector3f& pos, Vector3f& lookat, Vector3f& upAxis)
{
//Note _forward, _right, _up are working vector of type Vector3f

_up.set(upAxis);
_forward.sub(lookat, pos);
_forward.normalize();
_right.cross(_up, _forward);
_right.normalize();
_up.cross(_forward, _right);
_up.normalize();

m00 = _right.x;
m10 = _right.y;
m20 = _right.z;

m01 = _up.x;
m11 = _up.y;
m21 = _up.z;

m02 = _forward.x;
m12 = _forward.y;
m22 = _forward.z;

// Locate the camera
m03 = pos.x;
m13 = pos.y;
m23 = pos.z;

m30 = 0.f;
m31 = 0.f;
m32 = 0.f;

m33 = 1.f;
}

最佳答案

没有看到您在顶点着色器中做什么,我们只能猜测。但是,您可以在新的 OpenGL 中使用与旧的相同的矩阵。您可能没有的唯一矩阵是 gluPerspective,因此您可以自己实现它(以防您不再有 glu.h)。我这样做:

void glPerspective(double fovy,double aspect,double zNear,double zFar)
{
double per[16],f;
for (int i=0;i<16;i++) per[i]=0.0;
// original gluProjection
// f=divide(1.0,tan(0.5*fovy*deg))
// per[ 0]=f/aspect;
// per[ 5]=f;
// corrected gluProjection
f=divide(1.0,tan(0.5*fovy*deg*aspect));
per[ 0]=f;
per[ 5]=f*aspect;
// z range
per[10]=divide(zFar+zNear,zNear-zFar);
per[11]=-1.0;
per[14]=divide(2.0*zFar*zNear,zNear-zFar);
glLoadMatrixd(per);
// zNear=divide(-per[11],per[10]); // get znear from perspective projection matrix
}

它或多或少地模仿了 gluPerspective,但它修复了不准确的 tan,当将更多的截头体堆叠在一起时会导致问题。注释行显示了如何计算原始 gluPerspective(也修复了 tan),最后一条注释显示了如何从矩阵中获取 znear(用于光线追踪器) )

Of coarse 而不是 glLoadMatrixd(per); 你可以根据需要使用 per ...(比如发送 uniform)

现在要实现 lookat,您只需自己构建矩阵。见:

因此,您只需计算X,Y,Z vector 和O 原点位置

Z = -forward
X = +right
Y = +up
O = +camera_position - znear

并将它们送入您的矩阵中所需的位置...

现在如果你的lookat 是目标对象的位置而不是

Z = normalize(camera_position-lookat)
Y = up
X = cross(Y,Z)

不确定 X 应该是 + 还是 - 只是尝试,如果场景是镜像的,那么就否定它。

关于c++ - 从固定功能迁移到 GLSL OpenGL : How should I modify my view (lookAt) matrix and perspection matrix?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50573428/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com