65.9K
CodeProject 正在变化。 阅读更多。
Home

戴上您的红青眼镜

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.11/5 (2投票s)

2009年4月15日

MIT

5分钟阅读

viewsIcon

36450

downloadIcon

388

本文展示了如何在 WPF 中构建和显示立体图像。

引言

本文展示了如何在 Windows Presentation Foundation (WPF) 中构建和显示立体图像。WPF 已经具备了渲染 3D 图像的能力——我们只需增加一点深度。

背景

WPF 中的 3D

WPF 能够以透视方式显示 3D 模型——就像人类或相机看到的那样。在 WPF 中,3D 模型可以通过几何体(通常表示为三角形网格)和光源来描述。模型可以通过 `Viewport3D` 控件包含在 WPF 窗口/文档中。XAML 文档通常会包含以下代码

<Viewport3D>
    <Viewport3D.Camera>
        <PerspectiveCamera ... />
    </Viewport3D.Camera>
    <ModelVisual3D>
	...
    </ModelVisual3D>
</Viewport3D>

`Viewport3D` 控件需要相机描述才能渲染引用的 3D 模型。我们将使用 `PerspectiveCamera` 来描述模型的观看方式。

图:相机和模型项示例

立体图像

人类可以通过两只眼睛感知深度;大脑根据从两只眼睛接收到的图像判断物体有多远。向两只眼睛显示相同的图像或只使用一只眼睛会迫使大脑猜测物体的深度。

要制作立体图像,你需要两张图像:一张给一只眼睛,一张给另一只眼睛。为左眼拍摄的图像必须显示给左眼,为右眼拍摄的图像必须显示给右眼。通常使用两台相机来创建一对立体图像。通常,相机水平并排放置;相机镜头之间的距离应与人眼之间的距离相同。

图:为拍摄立体图像而放置的相机

有几种方法可以为不同的眼睛显示不同的图像。我们只关注其中三种:平行观看、交叉观看和差色法。前两种易于创建,但不易于观看。在平行观看中,两张图像(分别为左眼和右眼)并排打印,人眼试图聚焦在图像“后面”,以便让眼睛看到各自的图像。一个缺点是图像必须很小——图像的宽度不能超过眼睛之间的距离。在交叉观看中,两张图像被交换并排打印:先是右眼图像,然后是左眼图像;人眼试图聚焦在图像“前面”,以便让眼睛看到各自的图像。

图:立体图像对的交叉和平行观看

要观看典型的差色图像,你需要一副特殊的眼镜:一侧是红色玻璃,另一侧是青色(蓝色)玻璃。红玻璃帮助一只眼睛只看到红色(通道)颜色,而青玻璃帮助看到除红色之外的所有其他颜色。差色图像可以通过替换第一张图像(为右眼拍摄)的红色通道颜色,用第二张图像(为左眼拍摄)的红色通道颜色来构建。

像素着色器

.NET Framework 3.5 SP1 引入了基于像素着色器技术的自定义位图效果。像素着色器允许开发者使用高级着色语言 (HLSL) 创建代码,该代码可以在图像渲染过程中由图形处理单元 (GPU) 执行,以添加一些特殊效果。

WPF 库中的 `ShaderEffect` 类有助于封装与底层像素着色器对象和代码的接口。继承的 `SharedEffect` 类必须创建 `PixelShader` 对象并提供编译后的效果代码来执行实际计算。像素着色器代码将接受一个或多个位图图像和/或附加参数来产生输出。

Using the Code

代码包含 `AnaglyphEffects` 库和一个示例 3D WPF 应用程序。`AnaglyphEffects ` 库包含 `RedCyanEffect` 类,该类继承自 `ShaderEffect` 类。像素着色器的源代码如下所示

sampler2D input : register(s0);
sampler2D otherEye : register(s1);

float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 clr1;
clr1= tex2D(otherEye, uv.xy);

float4 Color;
Color= tex2D(input, uv.xy);

Color.r=clr1.r;

return Color;
}

代码接受两个图像作为输入。在执行过程中,它会将输入图像中的红色替换为另一个(`tex1`)图像的红色层。它允许从两个立体图像对构建差色图像。

图:RedCyanEffect 如何构建差色图像

示例 3D WPF 应用程序包含一个房屋的 3D 模型,该模型从两个相机的角度(左和右)进行观察。来自两个相机的输出使用 `AnaglyphEffects ` 库中的自定义差色位图效果(`RedCyanEffect` 类)进行合并。

<Rectangle Name="anaglyph"> 
    <Rectangle.Fill> 
        <VisualBrush Visual="{Binding ElementName=rightViewport}" Stretch="Uniform" /> 
    </Rectangle.Fill>            
    <Rectangle.Effect> 
        <ae:RedCyanEffect> 
            <ae:RedCyanEffect.OtherEye> 
                <VisualBrush Visual="{Binding ElementName=leftViewport}" 
						Stretch="Uniform" /> 
            </ae:RedCyanEffect.OtherEye> 
        </ae:RedCyanEffect> 
    </Rectangle.Effect> 
</Rectangle>

图:示例应用程序屏幕截图

关注点

令人惊讶的是,WPF 允许你在任何级别上操作输出:在控件绘制之前通过样式化它,在控件绘制之后通过应用位图效果,或者只是检索控件图像以在应用程序的其他部分重用它。`VisualBrush` 元素可以让你获取控件图像,对其进行转换,并将图像用作 `Brush`,例如,它可以用来创建反射。

自定义位图效果的创建非常简单,不需要了解如何针对不同处理器进行优化——框架会负责处理。像素着色器代码必须使用 `fxc` 命令行工具(DirectX SDK 的一部分)编译成中间代码,并作为嵌入资源附加到程序集中。编译后的代码用作 `ShaderEffect` 初始化期间的参数。

实现的 `RedCyanEffect` 可以应用于任何立体图像对,例如,为 JPEG (JPS) 立体图像构建差色查看器。

参考文献

  1. “WPF 基于 GPU 的效果系列”,Greg Schechter
  2. “http://en.wikipedia.org/wiki/Stereoscopy”,维基百科

历史

  • 2009 年 4 月 15 日:初始发布
© . All rights reserved.