zbuffermethod.htm

来自「电脑图学(Computer Graphics)是资料结构、演算法与数学的应用」· HTM 代码 · 共 161 行

HTM
161
字号
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>







  
  
  
  
  
  
  
  <link rel="stylesheet" href="css/stdlayout.css" type="text/css">







  
  
  
  
  
  
  
  <link rel="stylesheet" href="css/print.css" type="text/css">







  
  
  
  
  
  
  
  <meta content="text/html; charset=gb2312" http-equiv="content-type">







  
  
  
  
  
  
  
  <title>Z Buffer法</title>
</head>


<body>







<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>







<h1><a href="ComputerGraphics.htm">Computer Graphics: Z Buffer法</a></h1>







<a href="MaxMinMethod.htm">最大最小法</a> 仅适用于曲面函式可以用显函式y = f(x, z)来表示时,如果曲面函式非显函式形式,则无法使用最大最小法来处理深度问题。<br>
<br>
Z Buffer有些类似画家演算法,都是以近景遮盖远景的方法来处理深度问题,所不同的是Z
Buffer使用的是裁剪(culling)的方法,并以像素为处理的对象,Z
Buffer将绘图画布内所有的座标当作一个深度缓冲区阵列zbuf[]的索引,每一个zbuf[]的元素记录一个像素绘制时的Z深度资讯,可以使用它来
处理隐函式的图形绘制。<br>
<br>
假设画布大小为600X400(X,
Y),则zbuf[]的大小必须设定为600*400=240000(X*Y),一开始时所有zbuf[]元素的值设定为一个极小值,也就是所有的像素都
表示空间中一个极深的位置,开始绘制之后,必须在zbuf[]中记录每一个像素的z值。<br>
<br>
zbuf[]是个一维阵列,所以我们必须计算座标的索引值,如果以列为主的话,则(x, y)对应的zbuf[]元素值为:zbuf[x + y * 画布高度];当然您也可以使用二维阵列zbuf[][]来直接对应。<br>
<br>
如果后来要绘制的点之z值大于zbuf[]中记录的值,表示此点在之前所绘点的前面,于是绘制此点来覆盖之前所绘的点,并更新zbuf[]
中的z值为目前点的z值;如果后来要绘制的点之z值小于zbuf[]中记录的值,表示此点在之前所绘点的后面,于是不用绘制此点,当然也不用更新zbuf
[]中的z值。<br>
<br>
Z Buffer的深度处理方式无论从哪一个点开始绘制,都不会影响处理的结果;Z buffer的缺点就是使用大量的记忆体作为缓冲区,而由于它是以像素为处理的单位,所以需耗用相当大量的运算资源。<br>
<br>
下面这个程式并不是一个很好的示范,因为我们并不是每个像素都考虑到,但可以让您了解Z Buffer的演算法,如果要考虑所有的像素,这个程式要画的好,最好加上阴影的效果,绘制的图形之参数式如下,其中 a 表示圆的粗细: <br>







<div style="margin-left: 40px;"><span style="font-family: Courier New,Courier,monospace; font-weight: bold;">x = (1+a*cos&theta;) * sin&phi; </span><br style="font-family: Courier New,Courier,monospace; font-weight: bold;">
<span style="font-family: Courier New,Courier,monospace; font-weight: bold;">y = a * sin&theta; </span><br style="font-family: Courier New,Courier,monospace; font-weight: bold;">
<span style="font-family: Courier New,Courier,monospace; font-weight: bold;">z = (1+a*cos&theta;)*cos&phi; </span><br style="font-family: Courier New,Courier,monospace; font-weight: bold;">
<span style="font-family: Courier New,Courier,monospace; font-weight: bold;">0 &lt; a &lt; 1, 0 &lt;= &theta; &lt;= 2&pi;, 0 &lt;= &phi; &lt;= 2&pi; </span><br>
</div>








<br>







<span class="postbody"></span><br>
<ul>
  <li> ZBufferMethod.java
  </li>
</ul>

<pre>package onlyfun.caterpillar;<br> <br>import java.awt.Color;<br>import java.awt.Graphics;<br>import javax.swing.JApplet;<br> <br>public class ZBufferMethodDemo extends JApplet {<br>    private int orgX;<br>    private int orgY;<br>    private double[] zbuf; <br> <br>    public void init() {<br>        super.init();<br>        setBackground(Color.black);<br>        orgX = (int)getSize().width /2;<br>        orgY = (int) (getSize().height / 2);<br>        zbuf = <br>            new double[getSize().width * getSize().height];<br>    }<br>    <br>    public void paint(Graphics g) {<br>        g.setColor(Color.yellow);<br>        <br>        // 从斜角绘制<br>        // 绕 x 轴转 30 度<br>        double angleX = Math.toRadians(30);<br>        <br>        double a = 0.3;<br>        double k = 200.0;<br>        <br>        for(int l = 0; l &lt; zbuf.length; l++) <br>            zbuf[l] = -10000.0; <br>        <br>        // 由于是单色,调整一下 j 与 i 可以看的明显一些<br>        for(double j = 0; j &lt; 360; j+=0.2) {  <br>            for(double i = 0; i &lt; 360; i+=0.1) { <br>                double x = (1 + a*Math.cos(Math.toRadians(i))) * <br>                            Math.sin(Math.toRadians(j)); <br>                double y = a * Math.sin(Math.toRadians(i)); <br>                double z = (1 + a*Math.cos(Math.toRadians(i))) * <br>                            Math.cos(Math.toRadians(j)); <br><br>                // 立体旋转,从斜角绘制,调整绘图中心至视窗中心<br>                double pointX = orgX + k * x;<br>                double pointY = orgY - k * <br>                   (y*Math.cos(angleX) - z*Math.sin(angleX));<br>                <br>                // Z buffer处理<br>                int index = (int) (pointX + <br>                               pointY * getSize().width);<br>                if(z &gt; zbuf[index]) {<br>                    g.drawLine((int)pointX, (int)pointY, <br>                               (int)pointX, (int)pointY);<br>                    zbuf[index] = z;<br>                }<br>            } <br>        }<br>    }<br>}<br></pre>
<br>
<br>
<img style="width: 607px; height: 468px;" alt="" src="images/zBufferMethod-1.jpg"><br>
<br>
<br>







</body>
</html>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?