Thinking dynamic

Write here write now
随笔 - 19, 文章 - 0, 评论 - 2, 引用 - 0
数据加载中……

2007年11月28日

Z-Buffer 与 W-Buffer

Depth-Buffer(深度缓存)有两种:Z-Buffer 和 W-Buffer,这里讨论这两种深度缓存的区别,以及如何在两者之间转换。

w 的含义

3D空间点的坐标是(x,y,z),为了使矩阵乘法具有平移变换的功效,我们用4D空间中的点(x,y,z,w)来表示3D空间中的点(x',y',z'),这两个不同空间点之间的关系是:

    x' = x / w
    y' = y / w
    z' = z / w

像这样用四维空间点表示三维空间点,或者说用 n + 1 维空间点表示 n 维空间点的方法叫做 “齐次坐标表示法”。

实际使用中,在模型->世界转换、世界->视图转换过程中,w 通常保持不变,总是等于一,这样,齐次坐标的前三个分量就是对应3D空间点的三个坐标分量。但是,经过投影变换后,w 将得到一个比例值,比如,一般的透视投影变换矩阵是:

    | W   0   0   0 |
    | 0   H   0   0 |
    | 0   0   Q   1 |
    | 0   0  -QZn 0 |

    其中   Zn  =  近裁剪面 z 坐标
           Zf  =  远裁剪面 z 坐标
            W  =  2 * Zn / 视口宽度
            H  =  2 * Zn / 视口高度
            Q  =  Zf / (Zf - Zn)

将点(x,y,z,1)乘以此矩阵,w 便不再是一,而对应的3D空间点坐标(x / w,y / w,z / w)将出现一个缩放效果。同时,因为 w 的值通常与 z 坐标成正比(比如经过上面这个矩阵的变换,w 的值其实就是 z 坐标的值),所以经过投影变换,物体会产生近大远小的效果。

Z-Buffer 与 W-Buffer 的区别

简单的说,z-buffer 与 w-buffer 的区别就是前者保存的是点的 z 坐标,而后者保存的是点的 w 坐标。

具体的说,两者因为保存的值有不同的含义,所以表现出来的实际效果也会有差别。

z-buffer 保存的是经过投影变换后的 z 坐标,前面说过,投影后物体会产生近大远小的效果,所以距离眼睛比较近的地方,z 坐标的分辨率比较大,而远处的分辨率则比较小,换句话说,投影后的 z 坐标在其值域上,对于离开眼睛的物理距离变化来说,不是线性变化的(即非均匀分布),这样的一个好处是近处的物体得到了较高的深度分辨率,但是远处物体的深度判断可能会出错。

w-buffer 保存的是经过投影变换后的 w 坐标,而 w 坐标通常跟世界坐标系中的 z 坐标成正比,所以变换到投影空间中之后,其值依然是线性分布的,这样无论远处还是近处的物体,都有相同的深度分辨率,这是它的优点,当然,缺点就是不能用较高的深度分辨率来表现近处的物体。

从硬件实现角度来说,几乎所有的硬件3D加速卡都支持 z-buffer,而 w-buffer 的支持没有 z-buffer 那么广泛。另外,早期的 Direct3D 版本看起来也不支持 w-buffer。

Z-Buffer 与 W-Buffer 之间的转换

根据上面的矩阵变换,可以很容易的导出将 w-buffer 转换成 z-buffer 的公式:

    zDepth = Q * ( wDepth - Zn ) / wDepth
           = Zf / ( Zf - Zn ) * ( wDepth - Zn ) / wDepth

这个转换公式有什么用处?举个例子:3DS MAX 使用的是 w-buffer,如果从 3DS MAX 中导出深度信息到 Direct3D 中,作为预渲染的背景使用,就有可能用到上面这个转换。当然,如果在 D3D 中使用 w-buffer,问题就不大了,但是如果使用 z-buffer,不经过这样的转换,渲染结果就会出错。

posted @ 2007-12-01 16:59 cofd 阅读(37) | 评论 (0)编辑

亮度专业词语(转)

在计算机图形学方面有许多的表示亮度的专业词语。正确理解这些词语而不是简单地视为亮度能使你在处理图象时获得更好的效果。
1、什么是Intensity?
  这个词可以解释为强度,表示的是每单位面积传播的(光)辐射能量。Intensity也可以称为线形光测量,可以以诸如每平方米多少瓦此类的单位来衡量。提供给显示器阴极射线管(简称CRT)的电压直接控制了颜色构成的Intensity,但是却是以非线性方式的。所以CRT的电压与Intensity并不是成正比的。
2、什么是Birghtness?
  这个词解释为亮度(下面好几个词的解释都是亮度)。这是由Commission Internationale de L’Eclairage (CIE)根据一个区域发出的光的多少来定义的可视属性。Birghtness是知觉数值,没有固定的客观量度。
3、什么是Luminance?
  这个词解释为光照度,由CIE定义,以Y为表示符号,以视觉属性--光谱敏感性与辐射强度加权得出。Luminance的光度与物理强度成比例。Luminance容易使人觉得与Intensity差不多。但Luminance的频谱组成是与人类视觉的光敏感性相关的。
  Luminance可以以线性光的主要组成:红绿蓝三分量的适当加权和来计算。以目前的摄像设备为例,各系数为:
  在视频方面的标准是以非线性R’G’B’组成的加权和来计算LUMA组成Y’的。虽然这个数值经常被看作Luminance,但它不是。
4、什么是Lightness?
  这个词也是亮度。人类视觉对光的知觉是非线性的。一个Luminance只有另外一个光源的18%的光源,在人看来却是50%。对Luminance的知觉反应称为Lightness,并且被CIE定义为Luminance的修正立方根:
  Yn是参考白色的Luminance。如果你把Luminance(Y)常态化为参考白色那就不需要计算这个商。
  在另一方面,也可以说Lightness知觉是粗略对数的,你可以对Intensity相差只是百分之一多一点的两点发觉不同。
5、什么是Gamma?
  Gamma也是用于表示亮度。一个物理设备发出的光的Intensity通常都不是输入信号的线性输出。传统的CRT具有对电压的功率反应:在显示表面产生的Intensity大约是输入电压的2.5次方。这个数值通俗地称为Gamma。为能产生正确的Intensity必须对这一非线性进行补偿。
6、什么是Gamma校正?
  在视频系统,线性光Intensity通过Gamma校正转换为非线性的视频信号,通常在摄像过程内完成。如下函数把把线性光亮度(Intensity),R,转换为非线性组成R’:
  然后,一个理想的显示器把该转换反转输出:
7、什么是Contrast Ratio?
  Contrast Ratio是对比度的意思,也就是对某一设备或环境而言的最亮的白色和最暗的黑色之间的Intensity的比例。电影院的对比度可以达到80:1,电视在设计时认为你的居室环境是30:1,典型的办公条件下一个CRT显示器的对比度大约是5:1。
8、如何调节显示器的黑度和图象控制?
  一般的显示器上的标识都是错的。Picture Control,通常被标识为Contrast,控制整体亮度(Intensity),Black Level黑度控制,通常被标识为Birghtness,调整黑色偏重。显示一幅从纯白到纯黑过渡的图象,先调整黑度控制使得显示器显示完全是黑色,然后慢慢调节黑度,直到感觉上纯黑的部位开始变亮为止。这是因为图象是基于黑色显示的。当达到这一点后,标记下黑度控制的位置,然后显示一幅彩色图象(一般选取自然景观),调节图象控制到你喜欢的亮度。

posted @ 2007-11-29 17:06 cofd 阅读(44) | 评论 (0)编辑

Silverlight与Html/JavaScript互操作

前段时间写了Flex和JavaScript互操作, 本篇介绍Silverlight和Html/Javascript的互操作性.当然Silverlight可以使用多种托管语言, 我这里使用C#.

摘要:

先介绍一下System.Windows.Browser命名空间下的几个类, 接着介绍Silverlight如何操纵Html元素, 最后介绍如何从Javascript调用Silverlight的方法, 以及Silverlight调用Javascript方法.

1.System.Windows.Browser

Silverlight提供了一组对象来描述Html文档对象模型(DOM), 包括HtmlPage, HtmlDocument, HemlElement, HtmlElementCollection, 等等. 我们可以通过这些对象从Silverlight访问Html页面的内容, 如获取某个Html元素, 导航到新的URL等.(ps:Silverlight 1.1 Complete API List )

首先看HtmlPage类, 其提供了浏览器信息的静态属性BrowserInformation;提供的静态方法Navigate, 可以方便的跳转到其他的web页.提供了Document属性访问Html Dom, 有了它就可以干很多事了

HtmlDocument/HemlElement类用来访问DOM, 有了DOM就可以像Javascript一样做任何事了.

注意: 如果需要Silverlight可以访问Html页面的内容, 在创建Silverlight控件的时候必须将enableHtmlAccess设为true.

2.Silverlight操纵Html

想象Javascript是怎么访问Html元素的, Silverlight也同样可以.

修改页面属性:如修改页面标题, HtmlPage.Document.SetProperty("title", "new title");

操纵html元素:

HtmlElement elem =  HtmlPage.Document.GetElementByID("btn");
elem.SetAttribute("value", "haha");
elem.GetAttribute("value");

elem.AttachEvent("onclick", delegate(object sender, HtmlEventArgs he){
                // ...
            });

3.Javascript调用Silverlight方法

Javascript要想调用Silverlight, Silverlight必须通过DOM提供给Javascript一个可操作的对象.

新建一个silverlight项目, 修改Page.xaml.cs如下:

using System;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;

namespace SilverlightProject1
{
    [Scriptable]
    public partial class Page : Canvas
    {
        public void Page_Loaded(object o, EventArgs e)
        {
            // Required to initialize variables
            InitializeComponent();           

            WebApplication.Current.RegisterScriptableObject("js", this);           
        }

       [Scriptable]
       public string CalledByJs(string name)
        {
            return "i'm silverlight, called by " + name;
        }
    }
}

修改TestPage.html如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Silverlight Project Test Page </title>
    <script type="text/javascript" src="Silverlight.js"></script>
    <script type="text/javascript" src="TestPage.html.js"></script>
    <style type="text/css">
        .silverlightHost { width: 640px; height: 480px; }
    </style>
    <script type="text/javascript">
        function callSL()
        {
            var control = document.getElementById("SilverlightControl");
            var manager = control.Content.js;
            alert( manager.CalledByJs('js') );
        }
    </script>
</head>

<body>
    <div id="SilverlightControlHost" class="silverlightHost" >
        <script type="text/javascript">
            createSilverlight();
        </script>
    </div>
    <input id="btn" type="button" value="call silverlight method" onclick="callSL()" />
</body>
</html>

好像还不支持Silverlight方法返回一个复杂类型, 不过还好Silverlight内置了json的支持, 使用System.Windows.Browser.Serialization命名空间下JavaScriptSerializer序列化一下就ok了.

4.Silverlight调用Javascript方法

Silverlight无法直接调用javascript方法, 不过可以利用事件, 在Silverlight里抛出事件, 在javascript响应该事件.

修改Page.xaml如下:

<Canvas x:Name="parentCanvas"
        xmlns="http://schemas.microsoft.com/client/2007"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Loaded="Page_Loaded"
        x:Class="SilverlightProject1.Page;assembly=ClientBin/SilverlightProject1.dll"
        Width="640"
        Height="480"
        Background="White"
        >
  <TextBlock Text="call js method" MouseLeftButtonDown="OnClick"/>
</Canvas>

修改Page.xaml.cs如下:

using System;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Input;

namespace SilverlightProject1
{
    [Scriptable]
    public partial class Page : Canvas
    {
        public void Page_Loaded(object o, EventArgs e)
        {
            // Required to initialize variables
            InitializeComponent();           

            WebApplication.Current.RegisterScriptableObject("js", this);           
        }

        protected void OnClick(object sender, MouseEventArgs e)
        {
            if (this.CallJs != null )
            {
                EventHandler temp = this.CallJs;
                temp(this, EventArgs.Empty);
            }
        }

       [Scriptable]
        public event EventHandler CallJs;
    }
}

修改TestPage.html.js:在onLoad事件里添加了对Silverlight抛出的CallJs 事件的响应.

// JScript source code

//contains calls to silverlight.js, example below loads Page.xaml
function createSilverlight()
{
    Silverlight.createObjectEx({
        source: "Page.xaml",
        parentElement: document.getElementById("SilverlightControlHost"),
        id: "SilverlightControl",
        properties: {
            width: "100%",
            height: "100%",
            version: "1.1",
            enableHtmlAccess: "true"
        },
        events: { onLoad : OnLoaded}
    });
    // Give the keyboard focus to the Silverlight control by default
    document.body.onload = function() {
      var silverlightControl = document.getElementById('SilverlightControl');
      if (silverlightControl)
      {
        silverlightControl.focus();
      }
    }
}

function OnLoaded(sender, args)
{
    sender.Content.js.CallJs = calledBySL;
}

function calledBySL(sender, args)
{
    alert("i'm js, called by silverlight");
}

done!

我尝试了在Silverlight事件里加了自定义的参数, javascript这边好像接收不到??不知道是什么原因.

总结:

Silverlight与Javascript的互操作的方式和Flex类似, 不过个人还是喜欢Silverlight的方式, C#的语法简单清晰.

参考资料:

[Silverlight探秘]深入探索Silverlight与Javascript的交互

Silverlight 访问html元素

posted @ 2007-11-28 09:34 cofd 阅读(273) | 评论 (0)编辑