我有一个用于控制相机的相机类,主要功能是:
void PNDCAMERA::renderMatrix()
{
float dttime=getElapsedSeconds();
GetCursorPos(&cmc.p_cursorPos);
ScreenToClient(hWnd, &cmc.p_cursorPos);
double d_horangle=((double)cmc.p_cursorPos.x-(double)cmc.p_origin.x)/(double)screenWidth*PI;
double d_verangle=((double)cmc.p_cursorPos.y-(double)cmc.p_origin.y)/(double)screenHeight*PI;
cmc.horizontalAngle=d_horangle+cmc.d_horangle_prev;
cmc.verticalAngle=d_verangle+cmc.d_verangle_prev;
if(cmc.verticalAngle>PI/2) cmc.verticalAngle=PI/2;
if(cmc.verticalAngle<-PI/2) cmc.verticalAngle=-PI/2;
changevAngle(cmc.verticalAngle);
changehAngle(cmc.horizontalAngle);
rightVector=glm::vec3(sin(horizontalAngle - PI/2.0f),0,cos(horizontalAngle - PI/2.0f));
directionVector=glm::vec3(cos(verticalAngle) * sin(horizontalAngle), sin(verticalAngle), cos(verticalAngle) * cos(horizontalAngle));
upVector=glm::vec3(glm::cross(rightVector,directionVector));
glm::normalize(upVector);
glm::normalize(directionVector);
glm::normalize(rightVector);
if(moveForw==true)
{
cameraPosition=cameraPosition+directionVector*(float)C_SPEED*dttime;
}
if(moveBack==true)
{
cameraPosition=cameraPosition-directionVector*(float)C_SPEED*dttime;
}
if(moveRight==true)
{
cameraPosition=cameraPosition+rightVector*(float)C_SPEED*dttime;
}
if(moveLeft==true)
{
cameraPosition=cameraPosition-rightVector*(float)C_SPEED*dttime;
}
glViewport(0,0,screenWidth,screenHeight);
glScissor(0,0,screenWidth,screenHeight);
projection_matrix=glm::perspective(60.0f, float(screenWidth) / float(screenHeight), 1.0f, 40000.0f);
view_matrix = glm::lookAt(
cameraPosition,
cameraPosition+directionVector,
upVector);
gShader->bindShader();
gShader->sendUniform4x4("model_matrix",glm::value_ptr(model_matrix));
gShader->sendUniform4x4("view_matrix",glm::value_ptr(view_matrix));
gShader->sendUniform4x4("projection_matrix",glm::value_ptr(projection_matrix));
gShader->sendUniform("camera_position",cameraPosition.x,cameraPosition.y,cameraPosition.z);
gShader->sendUniform("screen_size",(GLfloat)screenWidth,(GLfloat)screenHeight);
};
它运行平稳,我可以用鼠标在 X 和 Y 方向控制角度,但不能围绕 Z 轴(Y 是世界空间中的“向上”)。
在我的渲染方法中,我使用一个 VAO 调用来渲染地形网格。网格本身是以四边形为中心(highes lod),其他网格是按 2 的幂缩放的 L 形网格。它总是在相机之前重新定位,缩放到世界空间,并由高度图移位。
rcampos.x = round((camera_position.x)/(pow(2,6)*gridscale))*(pow(2,6)*gridscale);
rcampos.y = 0;
rcampos.z = round((camera_position.z)/(pow(2,6)*gridscale))*(pow(2,6)*gridscale);
vPos = vec3(uv.x,0,uv.y)*pow(2,LOD)*gridscale + rcampos;
vPos.y = texture(hmap,vPos.xz/horizontal_scale).r*vertical_scale;
问题:
相机从原点开始,在(0,0,0)
。当我将它移离该点很远时,它会导致沿 X 轴的旋转不连续。感觉就像鼠标光标与屏幕空间中的网格对齐一样,只有网格点的位置被记录为光标移动。
当它变得非常明显时,我还记录了相机位置,它在 X 或 Z 方向上距离原点大约 1,000,000。我注意到这种“滞后”随着距离(从原点)线性增加。
在这一点上也有一点Z-fighting(或类似的效果),即使我使用没有位移的单个平面,并且没有平面可以重叠。(我使用镶嵌着色器和渲染补丁。)补丁上出现黑点。可能是雾引起的:
float fc = (view_matrix*vec4(Pos,1)).z/(view_matrix*vec4(Pos,1)).w;
float fResult = exp(-pow(0.00005f*fc, 2.0));
fResult = clamp(fResult, 0.0, 1.0);
gl_FragColor = vec4(mix(vec4(0.0,0.0,0.0,0),vec4(n,1),fResult));
另一个奇怪的行为是 Z 轴的小旋转,这也随着距离的增加而增加,但我不使用这种旋转。
变量格式:
顶点是unsigned short
格式,索引是unsigned int
格式。该cmc
结构是带有double
变量的相机/光标结构。
PI
并且C_SPEED
是#define
常数。
附加信息:
网格是用上面提到的ushort
数组创建的,间距为 1。在着色器中,我用一个常数对其进行缩放,然后使用 tessellation 来实现最佳性能和最大的视距。顶点的最终位置在细分评估着色器中计算。
mat4 MVP = projection_matrix*view_matrix*model_matrix;
如您所见,我使用glm库将矩阵发送到着色器。
+问:
浮点数(或任何其他格式)的长度如何导致这种“精度损失”,或任何导致问题的原因。这view_matrix
可能是造成这种情况的原因,但我仍然无法在运行时将其输出到屏幕上。
PS:我不知道这是否有帮助,但是关于“滞后开始位置”的视图矩阵是
-0.49662 -0.49662 0.863129 0
0.00514956 0.994097 0.108373 0
-0.867953 0.0582648 -0.493217 0
1.62681e+006 16383.3 -290126 1
编辑
比较相机位置和视图矩阵:
view matrix = 0.967928 0.967928 0.248814 0
-0.00387854 0.988207 0.153079 0
-0.251198 -0.149134 0.956378 0
-2.88212e+006 89517.1 -694945 1
position = 2.9657e+006, 6741.52, -46002