簡體   English   中英

GLSL鼠標懸停時高亮顯示網格

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM