C++ 从固定函数迁移到GLSL OpenGL:我应该如何修改我的视图(注视)矩阵和透视矩阵?
我正在尝试将我的OpenGL渲染管道从定点迁移到现代OpenGL。我的定点3D管线多年来运行良好。现在,当我切换到GLSL时,最终投影和对象方向看起来像“完全镜像或交换”。我排除了所有其他原因(如未能设置矩阵制服等),因为我可以通过随机拖动鼠标平移相机不时看到3D场景的渲染。因此,问题缩小到以下几点:C++ 从固定函数迁移到GLSL OpenGL:我应该如何修改我的视图(注视)矩阵和透视矩阵?,c++,opengl,glsl,shader,C++,Opengl,Glsl,Shader,我正在尝试将我的OpenGL渲染管道从定点迁移到现代OpenGL。我的定点3D管线多年来运行良好。现在,当我切换到GLSL时,最终投影和对象方向看起来像“完全镜像或交换”。我排除了所有其他原因(如未能设置矩阵制服等),因为我可以通过随机拖动鼠标平移相机不时看到3D场景的渲染。因此,问题缩小到以下几点: 生成视图矩阵的函数(my函数getViewMat(pos、lookat、upaxis)) 生成透视投影矩阵的函数(我的函数getPerspectiveMat(fov、aspect、nearZ、f
- 生成视图矩阵的函数(my函数getViewMat(pos、lookat、upaxis))
- 生成透视投影矩阵的函数(我的函数getPerspectiveMat(fov、aspect、nearZ、farZ))
/*
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;
}
/*
Matrix4f的类成员“float m00、m01、m02、m03、m10、m11、…、m33”表示
一个以行为主的4x4矩阵,当传递给GLSL时,我记得要转置它们
*/
void Matrix4f::_getPerspectiveByFov(浮点视野、浮点aspectRatio、浮点nearZ、浮点farZ、整数矩阵类型)
{
浮球半视场=MathUtil::degToRad(视场)*0.5f;
浮动宽度、高度;
//我们使用宽度和高度之外的小边作为基础尺寸,然后通过纵横比计算另一侧。
浮球_tanFOV=(浮球)tan(半浮球);
if(aspectRatio<1.f)//宽度较小
{
宽度=2.f*nearZ*u tanFOV;
高度=宽度/纵横比;
}
否则//高度会更小
{
高度=2.f*nearZ*_tanFOV;
宽度=高度*纵横比;
}
/*
来自OpenGL参考的公式,请参见函数“glFrustum”。
|w 0 0 0|
|0小时0小时|
|0-cd|
|0 0 1 0|
w=2.f*近Z/宽度
h=2.f*近Z/高度
C=-(法尔兹+尼尔兹)/(法尔兹-尼尔兹)
D=-2.f*farZ*nearZ/(farZ-nearZ);
*/
float w=2.f*nearZ/width;//等于:[1.f/tan(视野*0.5f)]
float h=2.f*nearZ/height;//等于:[1.f/tan(视野*0.5f)/aspectRatio]
浮点数C=-(法尔兹+近兹)/(法尔兹-近兹);
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;
}
无效矩阵4f::_getLookAt(向量3f&pos、向量3f&lookat、向量3f&upAxis)
{
//注(前),(右),(上)是向量3f型的工作向量
_向上。设置(向上轴);
_前方潜艇(了望,位置);
_forward.normalize();
_对。交叉(向上,向前);
_对,normalize();
_向上。交叉(向前,向右);
_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;
//找到摄像机的位置
m03=位置x;
m13=位置y;
m23=位置z;
m30=0.f;
m31=0.f;
m32=0.f;
m33=1.f;
}
没有看到你在顶点着色器中做什么,我们只能猜测。但是,您可以在新OpenGL中使用与旧OpenGL中相同的矩阵。您可能没有的唯一矩阵是glu透视图
,因此您可以自己实现它(以防您不再有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
}
然后在你想要的位置将它们输入矩阵
现在,如果您的lookat
是目标对象的位置,则
Z = normalize(camera_position-lookat)
Y = up
X = cross(Y,Z)
不确定
X
应该是+还是-只要尝试一下,如果场景被镜像,那么就否定它。感谢您的输入,添加所有源代码有点困难,我将尝试修改我的问题。1。我的4x4矩阵是行占优矩阵,我在发送到着色器(如果我忘记了,渲染结果是黑屏)2时对它们进行了转置。当我在着色器中乘以矩阵时,我这样做了:mat4 mat_vm=mat_view*mat_model;mat4 mat_pvm=mat_项目*mat_vm;按照其他帖子的建议,在计算投影矩阵后,我对z值求反:m02*-1,-m12*-1,-m22*-1,m32*-1,就像你建议的那样。但我开始看到黑屏,直到我随机否定视图矩阵中的一些值,使其出现。但是我不知道调整视图矩阵的正确方法?没有看到你在顶点着色器中做什么,我们只能猜测…虽然在看到你的答案之前我已经解决了我的问题,但是你的信息非常有用,谢谢!我的问题是,在My lookat()函数中生成的pos lookat axis矩阵是摄影机的世界变换矩阵,我应该使用其逆矩阵作为“视图”矩阵传入顶点着色器。
Z = normalize(camera_position-lookat)
Y = up
X = cross(Y,Z)