[英]GLSL highlight mesh on mouse over
我正在為我的opengl項目開發一個raycaster,我希望能夠突出顯示我懸停的網格部分。
我使用以下命令從鼠標位置獲取方向矢量:
glm::vec3 Engine::Physics::RayCast::ViewToWorldSpace(glm::vec2 screenPos,
float depth, glm::mat4 projection, glm::mat4 view, graphics::Window* window)
{
//Screen to Normalised Device Coordinates
float x = (2.0f * screenPos.x) / window->getWidth() - 1.0f;
float y = 1.0f - (2.0f * screenPos.y) / window->getHeight();
float z = 1.0f;
glm::vec3 ray_nds = glm::vec3(x, y, z);
//Normalised Device Coordinates to 4d Homogeneous Clip Coordinates
glm::vec4 ray_clip = glm::vec4(ray_nds.x, ray_nds.y, -1.0, 1.0);
//4d Homogeneous Clip Coordinates to Eye (Camera) Coordinates
glm::vec4 ray_eye = glm::inverse(projection) * ray_clip;
ray_eye = glm::vec4(ray_eye.x, ray_eye.y, -1.0, 0.0);
//Eye (Camera) Coordinates to 4d World Coordinates
glm::vec3 ray_wor = glm::inverse(view) * ray_eye;
ray_wor = glm::normalize(ray_wor);
return ray_wor;
}
然后,我想檢查是否指向網格的一部分,因此將相機位置和此方向向量傳遞給這些着色器。
頂點
#version 410
layout (location = 0) in vec3 vertex_position;
layout (location = 2) in vec2 VertexUV;
uniform mat4 P;
uniform mat4 V = mat4(1.0);
uniform mat4 M = mat4(1.0);
out vec2 uv;
out vec4 position;
uniform vec3 cam_pos;
out vec3 cameraPos;
uniform vec3 ray_dir;
out vec3 rayDir;
void main () {
rayDir = vec3(M * vec4(ray_dir,1.0));
cameraPos = vec3(V * M * vec4(cam_pos,1.0));
gl_Position = P * V * M * vec4(vertex_position, 1);
position = V * M * vec4(vertex_position, 1.0);
uv = VertexUV;
}
易碎
#version 410
out vec4 fragment_colour; // final colour of surface
in vec4 position;
in vec2 uv;
uniform vec3 light_pos;
uniform vec3 light_ambient;
uniform sampler2D texture2D;
in vec3 cameraPos;
in vec3 rayDir;
void main () {
vec4 test = vec4(0, 0, 0, 0);
vec3 vDir = normalize(position.xyz - cameraPos);
float cosAngle = dot(vDir, rayDir);
float angle = degrees(acos(cosAngle));
if(angle < 5)
{
test = vec4(1, 0, 0, 1);
}
float intensity = (1.0 / length(position.xyz - light_pos))+0.25;
intensity = clamp(intensity, 0, 1);
vec4 ambient = vec4(light_ambient, 1);
fragment_colour = ((vec4(texture(texture2D, uv).rgb, 1.0) * intensity) *
ambient)+test;
}
目前,我有時可以在某些相機旋轉時看到突出顯示部分(相機圍繞模型旋轉),但是只有當相機直接面向-Z軸時,它才會真正跟隨鼠標。 知道我在做什么錯嗎?
這是與相機對准時工作的效果的圖片,但請記住,如果相機移動,它會破裂。
在渲染中,通常通過模型矩陣,視圖矩陣和投影矩陣來變換場景的每個網格。
投影矩陣:
投影矩陣描述了從場景的3D點到視口的2D點的映射。
查看矩陣:
視圖矩陣描述了從中查看場景的方向和位置。 視圖矩陣從世界空間轉換為視圖(眼睛)空間。
模型矩陣:
模型矩陣定義場景中網格的位置,方向和相對大小。 模型矩陣將頂點位置從網格轉換為世界空間。
您決定在片段着色器中使用視圖空間坐標進行操作。
在片段着色器中,頂點位置( position
)在視圖空間中,因為您已在頂點着色器中對其進行了變換。 模型的頂點通過矩陣M
轉換為世界空間,並通過矩陣V
從世界空間轉換為視圖空間:
position = V * M * vec4(vertex_position, 1.0);
但是,攝像機的位置坐標( cam_pos
)是世界空間坐標。 這意味着您僅需通過視圖矩陣V
對其進行變換。
cameraPos = vec3( V * vec4(cam_pos, 1.0) );
請注意,此操作的結果vec3(0.0, 0.0, 0.0)
為vec3(0.0, 0.0, 0.0)
,因為攝像機的視圖空間位置是視圖空間的原點。 眼睛位置定義了視圖空間系統(矩陣)的原點:
cameraPos = vec3( 0.0, 0.0, 0.0 );
此外, rayDir
是方向矢量,而不是點。 這意味着您無法通過4 * 4矩陣對其進行轉換,因為您不想將矩陣的轉換部分應用於該矩陣。 通常,在變換方向向量時,必須使用4 * 4矩陣左上3 * 3的轉置逆。 但是,由於視圖矩陣是正交矩陣,因此使用左上方的3 * 3就足夠了。
rayDir
是世界空間中的一個方向,因此您僅需通過視圖矩陣V
對其進行變換。
rayDir = mat3(V) * ray_dir;
注意,如果省略了射線從視圖空間到世界空間的轉換,請在函數Engine::Physics::RayCast::ViewToWorldSpace
:
// glm::vec3 ray_wor = glm::inverse(view) * ray_eye; // skip this
ray_eye = glm::normalize(ray_eye);
return ray_eye;
那么您也可以在頂點着色器中省略向后轉換:
rayDir = ray_dir;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.