You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Glium+Glutin中获取鼠标的X和Y坐标?

获取Glium中鼠标点击坐标并转换为OpenGL坐标

一、获取窗口像素坐标

要获取鼠标点击位置,需在事件循环中监听两类窗口事件:

  • CursorMoved:实时更新鼠标在窗口内的像素坐标
  • MouseInput:检测鼠标按键点击动作,读取已记录的鼠标坐标

修改你的事件处理代码,添加鼠标位置存储和事件匹配逻辑:

/* ... */
// 在event.run外部定义变量存储鼠标位置
let mut mouse_pos = (0.0, 0.0);
// 获取窗口尺寸(用于后续坐标转换)
let window = /* 你的Glium窗口实例 */;
let mut window_size = window.get_inner_size().unwrap().to_logical::<f32>(window.scale_factor());

event.run(move |event, _, control_flow| {
    match event {
        glutin::event::Event::WindowEvent { event, .. } => match event {
            glutin::event::WindowEvent::CloseRequested => {
                println!("Received termination signal.");
                *control_flow = glutin::event_loop::ControlFlow::Exit;
                return;
            },
            // 监听鼠标移动,更新位置(适配高DPI窗口)
            glutin::event::WindowEvent::CursorMoved { position, .. } => {
                let logical_pos = position.to_logical::<f32>(window.scale_factor());
                mouse_pos = (logical_pos.x, logical_pos.y);
            },
            // 监听左键点击事件
            glutin::event::WindowEvent::MouseInput { state, button, .. } => {
                if button == glutin::event::MouseButton::Left && state == glutin::event::ElementState::Pressed {
                    println!("点击位置(窗口像素坐标):X={}, Y={}", mouse_pos.0, mouse_pos.1);
                    // 在此处执行渲染图片到该位置的逻辑
                }
            },
            // 监听窗口大小变化,更新尺寸
            glutin::event::WindowEvent::Resized(size) => {
                window_size = size.to_logical::<f32>(window.scale_factor());
            },
            _ => return,
        },
        glutin::event::Event::NewEvents(cause) => match cause {
            glutin::event::StartCause::ResumeTimeReached { .. } => (),
            glutin::event::StartCause::Init => (),
            _ => return,
        },
        _ => return,
    }
});

二、转换为OpenGL标准化设备坐标(NDC)

如果需要直接使用OpenGL的坐标范围(-1到1),可通过以下公式将窗口像素坐标转换为NDC坐标:

  • X轴:ndc_x = (2.0 * window_x) / window_width - 1.0
  • Y轴:ndc_y = 1.0 - (2.0 * window_y) / window_height(窗口Y轴向上递增,而OpenGL NDC Y轴向下递增,需反转)

在点击事件中添加转换逻辑:

// 鼠标点击事件内
if button == glutin::event::MouseButton::Left && state == glutin::event::ElementState::Pressed {
    let (win_x, win_y) = mouse_pos;
    let (win_width, win_height) = (window_size.width, window_size.height);
    
    let ndc_x = (2.0 * win_x) / win_width - 1.0;
    let ndc_y = 1.0 - (2.0 * win_y) / win_height;
    
    println!("点击位置(OpenGL NDC坐标):X={}, Y={}", ndc_x, ndc_y);
    // 直接使用ndc_x和ndc_y构建顶点缓冲区,无需额外矩阵变换即可渲染到对应位置
}

关键说明

  • 高DPI适配:使用to_logical方法将物理坐标转换为逻辑坐标,避免高分辨率屏幕下的坐标偏移
  • 窗口尺寸更新:监听Resized事件同步窗口尺寸,确保坐标转换的准确性
  • 简化顶点缓冲区:使用NDC坐标时,可直接将其作为图片顶点位置,省去视图/投影矩阵的额外计算

内容的提问来源于stack exchange,提问作者AggelosT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 07:03:19