[英]How to solve camera rotation along the X-axis?
我有一個 Opengl 光線追蹤器,它能夠加載 obj 文件並以光線追蹤的方式將其可視化。 我的應用程序使用 assimp 加載 obj 文件,然后使用着色器存儲緩沖區將所有三角形面(包括頂點及其索引)發送到片段着色器。 之后,片段着色器通過跟蹤光線的路徑來計算像素的顏色。 光線來自相機 ( posCamera
) 的 position 並穿過虛擬 canvas 的像素。 基本結構即將將結果渲染到這個四邊形 canvas。
目前,我正在研究相機。 相機始終注視着0,0,0
點 ( viewPoint
),並且可以通過下面的 function 圍繞 y 軸旋轉:
void setCamera(float param) {
connect = posCamera - viewPoint;
posCamera = glm::vec3(connect.x * cos(param) + connect.z * sin(param), connect.y,
-connect.x * sin(param) + connect.z * cos(param)) + viewPoint;
canvasX = cross(upVector, connect) * getLength(connect) * tanf(fieldOfview / 2);
canvasY = cross(connect, canvasX) * getLength(connect) * tanf(fieldOfview / 2);
setCam(posCamera,viewPoint, canvasY, fieldOfview);
我也只想圍繞 x 軸旋轉場景。 為了解決這個問題,我創建了一個新的 function:
void rotateAroundX(float param) {
connect = posCamera - viewPoint;
posCamera = glm::vec3(posCamera.x,
connect.y * cos(param) + connect.z * sin(param),
-connect.y * sin(param) + connect.z * cos(param))+viewPoint;
canvasX = cross(upVector, connect) * getLength(connect) * tanf(fieldOfview / 2);
canvasY = cross(connect, canvasX) * getLength(connect) * tanf(fieldOfview / 2);
setCam(posCamera,viewPoint, canvasY, fieldOfview);
}
它正在工作,但不幸的是,該比率存在一些失真。 更重要的是,有時相機只是圍繞一個點循環。 這是一個與問題相關的視頻:鏈接。 你可以看到水平旋轉做得很好。
這是我的頂點着色器:
#version 460 core
layout(location = 0) in vec2 normQuadCoord;
uniform vec3 viewPoint;
uniform vec3 canvasX, canvasY;
out vec3 pixel;
void main()
{
pixel = canvasX * normQuadCoord.x + canvasY * normQuadCoord.y + viewPoint;
gl_Position = vec4(normQuadCoord, 0, 1);
}
這是完整源代碼的鏈接: source
除了相機旋轉之外,我不知道這種“渲染到四邊形”概念是否可以實現自由飛行的相機。 任何幫助表示贊賞!
我嘗試了 Rabbid76 的建議並修改了源代碼。 我也做了一些重構。 更新矩形 canvas 尺寸的方法如下所示:
void Init::updateCanvasSizes() {
connect = camera.getPosCamera() - camera.getViewPoint();
float aspect = (float)SCR_W_H.first/(float)SCR_W_H.second;
float length = tanf(camera.getFieldOfview() / 2);
canvasX = glm::normalize(glm::cross(camera.upVector, connect)) / length / aspect;
canvasY = glm::normalize(glm::cross(connect, canvasX)) / length;
}
處理相機繞 X 軸旋轉的方法修改為:
void Init::rotateCamAroundX(float param) {
camera.posCamera = glm::vec3(camera.posCamera.x,
(camera.posCamera.y - camera.viewPoint.y) * cos(param) + (camera.posCamera.z - camera.viewPoint.z) * sin(param) + camera.viewPoint.y,
-(camera.posCamera.y - camera.viewPoint.y) * sin(param) + (camera.posCamera.z - camera.viewPoint.z) * cos(param) + camera.viewPoint.z);
updateCanvasSizes();
}
視野已從45
度修改為45 * (float)M_PI / 180
,因此 model 的比率變得更好一些。 不幸的是,在相機繞 X 軸旋轉的過程中,仍然可以發現場景拉伸和失真。 當相機達到一定程度時,它也會回過頭來查看camera.viewPoint
。 我不知道如何“關閉它”。
結果可以在這個視頻中看到: 鏈接。 首先可以看到繞 Y 軸的旋轉,然后可以看到繞 X 軸的旋轉。
您必須尊重視口的縱橫比。
在計算射線方向的點時, canvasX
和canvasY
會考慮縱橫比。
p = pixel = canvasX * normQuadCoord.x + canvasY * normQuadCoord.y + viewPoint;
如果視口是矩形的,則向量的大小必須不同。 canvasX
是從中心到右側的向量, canvasY
是從中心到視口頂部的向量。 為了補償視圖的矩形性並獲得正確的投影,矢量長度的比率必須等於縱橫比的倒數:
width | canvasY |
-------- = -----------
height | canvasX |
因此, canvasX
的長度必須按倒數縱橫比進行縮放。 縱橫比是視圖的寬度和高度的商( (float)SCR_WIDTH/(float)SCR_HEIGHT
):
float aspect = (float)SCR_WIDTH/(float)SCR_HEIGHT;
float length = tanf(fieldOfview / 2);
canvasX = glm::normalize(glm::cross(upVector, connect)) / length / aspect;
canvasY = glm::normalize(glm::cross(connect, canvasX)) / length;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.