如何扭曲桌面屏幕

5
我想改变桌面屏幕的形状,这样在桌面上显示的内容也会同时扭曲。用户仍然可以通过鼠标在扭曲的桌面上操作电脑(运行应用程序,打开“我的电脑”等)。我认为首先必须获取屏幕坐标的投影矩阵。然后转换矩阵,将桌面缓冲图像映射到扭曲的网格上。是否有任何接口可以在OpenGL或DirectX中修改桌面屏幕的形状?请给我一些提示。非常感谢您的帮助。
请参考以下图片:http://oi53.tinypic.com/bhewdx.jpg 致敬, Haifeng
添加1: 非常抱歉!也许我没有清楚地表达我想实现的内容。我想实现的是修改屏幕的形状。因此,我们可以同时扭曲所有在Windows上运行的应用程序的形状。例如,“我的电脑”窗口的形状将随着桌面屏幕的扭曲而扭曲。我们仍然可以通过鼠标从扭曲的桌面操作电脑(单击快捷方式运行程序)。
添加2: 投影矩阵只是我的假设。没有任何桌面投影矩阵可以将桌面表面投射到屏幕上。我想实现的是改变桌面的形状,就像将桌面映射到一个3D网格一样。但是用户仍然可以在扭曲的桌面上操作操作系统(单击快捷方式运行程序,打开IE浏览器上网)。
添加3: 所有在操作系统上运行的程序的形状都随着屏幕的扭曲而改变。这是实时的。用户仍然可以像通常一样在扭曲的屏幕上操作操作系统。
也许我们可以拦截或覆盖GPU本身来实现效果。
我正在调查GDI,我认为我可以找到一些线索。第一步是找出如何在屏幕上显示桌面。

你的意思是像旧款CRT屏幕和投影仪上可以找到的设置吗? - Calvin1602
是的。但我想通过软件设置来控制屏幕的形状。然后,在改变屏幕形状之后,所有在操作系统上运行的程序的形状都会改变,我们可以在扭曲的屏幕上控制操作系统。Calvin,你能给我一些提示吗?谢谢! - HaifengWang
注意,这些方法已经被专利保护:http://www.faqs.org/patents/app/20090102862 - Ben Voigt
5个回答

1

由于 Window Seven 使用 Direct3D API 渲染桌面,因此可能可以通过使用 detours 钩取 dwm.exe 进程并更改将桌面表面投影到屏幕的方式。据我所知,没有 DWM API 可用于执行此操作。


谢谢!我已经阅读了一些关于DWM和WDDM的材料。我认为Aero API可以以某种特殊形状渲染应用程序窗口,甚至在三维坐标中。但是我想做的是通过修改投影矩阵来投影桌面表面到屏幕上。如果我们实现了这个功能,“我的电脑”窗口将会随着桌面屏幕的扭曲而变形。因此,我们可以扭曲运行在Windows上的所有应用程序的形状。我正在调查的一个方向是Windows的低级接口。然后还应该调查显示驱动程序。 - HaifengWang

1

首先,你发布的链接使用了一些复杂的形状,而不是简单的四边形,因此仅使用投影矩阵就无法获得那种效果。你需要将当前桌面图像作为纹理,并将该纹理映射到网格上。请注意,你仍然可以使用简单的四边形来实现这一点,但它会产生更简单的效果(我仍建议你首先尝试这个来调试你的设置)。

如何捕获桌面内容:

基本上有两种方法(API)可以做到这一点。第一种是老派的方法,只能给你一个快照(很难在特效开始后仍然使用你的桌面)。第二种方法将为你提供更多的交互支持,但不适用于Windows XP。

  1. 使用Windows GDI函数(可以使用GDI+或.NET)来捕获桌面内容,并使用BitBlt()将其保存到DIB位图中--这就是您桌面上的“打印屏幕”按钮所做的事情,只不过它将图像放到了剪贴板中。然后,将其映射到OpenGL/DirectX纹理并继续进行其他操作。
  2. 使用新的Windows DWM缩略图功能代理桌面。有一些文档介绍如何将其用于合成效果。

如何使用桌面内容:

这涉及几个步骤,根据您选择的DirectX或OpenGL,代码会有很大的变化。

  1. 创建一个支持3D渲染的全屏窗口(即为该窗口设置OpenGL或DirectX,或使用一些具有内置支持的框架)。
  2. 捕获桌面内容(方法1:在启动时一次性捕获,方法2:在事件循环中重复捕获)
  3. 将桌面内容从位图传输到纹理。
  4. 创建表面(四边形或网格)并映射纹理。
  5. 更新您的窗口。

更多细节:

实现这需要对以下知识有很好的了解:

  1. 使用DirectX或OpenGL进行3D动画
  2. Windows中的高级UI编程

您可能没有实现此功能所需的所有知识,因此我建议您花些时间研究所请求的API并规划应用程序中的数据流。

此外,本帖子故意含糊不清。当您需要有关使用特定API涉及的不同步骤的更多详细信息时,请随时在SO上提出其他更专注的问题!


谢谢André给我提供了这么多信息!我们可以通过您的方法将桌面映射到网格上。但是我也想在畸变的桌面上操作操作系统,所有程序都会在畸变的桌面上运行。例如,单击快捷方式运行程序。如果打开“我的电脑”,则“我的电脑”的窗口也会变形。如果播放视频,则视频也将在扭曲的屏幕上播放。 - HaifengWang

0

问题9.100和9.110在这里的内容如下:

9.100 如何找到给定对象空间坐标的屏幕坐标?

如果您只需要为几个顶点找到它,可以使用GLU库的gluProject()实用程序例程。对于大量坐标,使用反馈机制可以更有效。

要使用gluProject(),您需要提供ModelView矩阵、投影矩阵、视口和输入对象空间坐标。返回X、Y和Z的屏幕空间坐标,其中Z被归一化(0 <= Z <= 1)。

9.110 如何找到屏幕上像素的对象空间坐标?

GLU库提供了gluUnProject()函数来实现此目的。

您需要读取深度缓冲区以获取感兴趣的X,Y位置处的输入屏幕坐标Z值。这可以编码如下:

GLdouble z;

glReadPixels (x, y, 1, 1, GL_DEPTH_COMPONENT, GL_DOUBLE, &z);

请注意,x和y是以OpenGL为中心的,其中(0,0)位于左下角。
您需要将屏幕空间X、Y和Z值作为输入提供给gluUnProject(),同时包括在感兴趣的特定像素渲染时当前的ModelView矩阵、Projection矩阵和视口。

这个OpenGl教程介绍了如何使用以下方法重置投影矩阵

glMatrixMode(GL_PROJECTION);        // Select The Projection Matrix
glLoadIdentity();                  // Reset The Projection Matrix

// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW);     // Select The Modelview Matrix
glLoadIdentity();                 // Reset The Modelview Matrix

0

我不知道在Windows上如何做到这一点,但是通过AIGLX合成,在X11上创建这些效果相当容易。这样的合成器之一是Compiz。因此,也许值得看看那个。

我知道你想在Windows上完成它,但是也许先熟悉一个已经可以实现这个功能的系统可能是一个好主意。


谢谢!我看了一段Compiz的视频,很酷!但这不是我想要实现的。我想做的是通过修改投影矩阵来投影桌面表面到屏幕上。如果我们实现了这个功能,“我的电脑”窗口将会随着桌面屏幕的扭曲而变形。因此,我们可以扭曲在Windows上运行的所有应用程序的形状。 - HaifengWang
这假设渲染桌面时使用了投影矩阵,这仅适用于使用3D API合成的桌面。纯2D桌面不需要任何投影矩阵。 - Dr. Snoopy
你所链接的截图效果不能通过简单的矩阵实现。这是一个复杂的非线性效果。此外,通常不会对桌面进行投影(好吧,Aero和Compiz确实改变了这一点)。但你不会找到一些桌面投影矩阵来修改。 - datenwolf
@Matias,谢谢!投影矩阵是我的假设。 - HaifengWang

0

不,你不想“修改投影矩阵,通过该矩阵将桌面表面投影到屏幕上”。

桌面表面并没有投影到屏幕上。它是2D的,因此只是在两个数组之间进行简单的memcpy()(其中一个数组恰好在显卡上)

基本思路如下:

  • 让操作系统在纹理中渲染桌面,而不是标准帧缓冲区。
  • 清除屏幕
  • 显示一些三角形,并用“桌面”纹理化

这应该在Linux上使用Compiz是可能的,正如dantenwolf所建议的那样,在Vista上非常困难,使用tibur的想法,而在XP上几乎不可能。

你给出的截图是在XP下的。我怀疑这实际上是第二个屏幕,甚至是第二台计算机。桌面以标准方式呈现,然后截取屏幕截图,并在另一个屏幕上的摇晃对象上呈现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接